mirror of
https://github.com/MasterAcnolo/Freedom-Loader.git
synced 2026-07-29 18:25:47 +02:00
Compare commits
19 Commits
2fb6509edc
...
1.6.0
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b321a1d164 | ||
|
|
89e6fcf9bc | ||
|
|
ba2f317551 | ||
|
|
553e383c94 | ||
|
|
89cc0b85a3 | ||
|
|
abd0bf9006 | ||
|
|
653f73805e | ||
|
|
4f03c5876f | ||
|
|
a5f05f32af | ||
|
|
0d1b1e4919 | ||
|
|
0e77a94ec7 | ||
|
|
7f481d20b2 | ||
|
|
1ff32ca021 | ||
|
|
90d8a9f65d | ||
|
|
d5965c2ce0 | ||
|
|
15f59a6093 | ||
|
|
8b31436e25 | ||
|
|
7d5203001b | ||
|
|
60709c4fad |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -4,6 +4,7 @@
|
|||||||
# Build Output Folder
|
# Build Output Folder
|
||||||
/dist
|
/dist
|
||||||
/out
|
/out
|
||||||
|
/srpm-out
|
||||||
|
|
||||||
# Config JSON File. Create it and fill it if you want to have dev only settings
|
# Config JSON File. Create it and fill it if you want to have dev only settings
|
||||||
config/config.dev.json
|
config/config.dev.json
|
||||||
|
|||||||
96
BINARIES.md
Normal file
96
BINARIES.md
Normal file
@@ -0,0 +1,96 @@
|
|||||||
|
# External binaries
|
||||||
|
|
||||||
|
This project depends on three external tools that are **not bundled in the repository**.
|
||||||
|
You must download them manually and place each binary in the correct folder before building or running the app locally.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Required tools
|
||||||
|
|
||||||
|
| Tool | Role |
|
||||||
|
|---------|---------------------------------------------|
|
||||||
|
| yt-dlp | Video and audio download engine |
|
||||||
|
| ffmpeg | Media encoding, transcoding, muxing |
|
||||||
|
| ffprobe | Media file analysis and metadata extraction |
|
||||||
|
| deno | JavaScript / TypeScript runtime |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Folder structure
|
||||||
|
|
||||||
|
Place the binaries exactly as shown below.
|
||||||
|
Do not rename them — the application resolves them by these exact names.
|
||||||
|
|
||||||
|
```
|
||||||
|
resources/
|
||||||
|
└── binaries/
|
||||||
|
├── linux/
|
||||||
|
│ ├── yt-dlp
|
||||||
|
│ ├── ffmpeg
|
||||||
|
│ ├── ffprobe
|
||||||
|
│ └── deno
|
||||||
|
└── win-32/
|
||||||
|
├── yt-dlp.exe
|
||||||
|
├── ffmpeg.exe
|
||||||
|
├── ffprobe.exe
|
||||||
|
└── deno.exe
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Download links
|
||||||
|
|
||||||
|
### yt-dlp
|
||||||
|
|
||||||
|
| Platform | URL |
|
||||||
|
|----------|----------------------------------------------------------------------|
|
||||||
|
| Windows | https://github.com/yt-dlp/yt-dlp/releases/latest/download/yt-dlp.exe |
|
||||||
|
| Linux | https://github.com/yt-dlp/yt-dlp/releases/latest/download/yt-dlp |
|
||||||
|
|
||||||
|
Rename the downloaded file to `yt-dlp` (or `yt-dlp.exe` on Windows).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### ffmpeg and ffprobe
|
||||||
|
|
||||||
|
**Windows and Linux** — both binaries are included in the same archive.
|
||||||
|
|
||||||
|
| Platform | URL |
|
||||||
|
|-------------|-----------------------------------------------------------------------------------------------------------|
|
||||||
|
| Windows x64 | https://github.com/BtbN/FFmpeg-Builds/releases/download/latest/ffmpeg-master-latest-win64-gpl.zip |
|
||||||
|
| Linux x64 | https://github.com/BtbN/FFmpeg-Builds/releases/download/latest/ffmpeg-master-latest-linux64-gpl.tar.xz |
|
||||||
|
| Linux arm64 | https://github.com/BtbN/FFmpeg-Builds/releases/download/latest/ffmpeg-master-latest-linuxarm64-gpl.tar.xz |
|
||||||
|
|
||||||
|
Extract the archive and copy `ffmpeg` and `ffprobe` from the `bin/` subfolder.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### deno
|
||||||
|
|
||||||
|
| Platform | URL |
|
||||||
|
|-------------|----------------------------------------------------------------------------------------------|
|
||||||
|
| Windows x64 | https://github.com/denoland/deno/releases/latest/download/deno-x86_64-pc-windows-msvc.zip |
|
||||||
|
| Linux x64 | https://github.com/denoland/deno/releases/latest/download/deno-x86_64-unknown-linux-gnu.zip |
|
||||||
|
| Linux arm64 | https://github.com/denoland/deno/releases/latest/download/deno-aarch64-unknown-linux-gnu.zip |
|
||||||
|
|
||||||
|
Each archive contains a single binary. Rename it to `deno` (or `deno.exe` on Windows).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Permissions (Linux )
|
||||||
|
|
||||||
|
After placing the binaries, make them executable:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
chmod +x resources/binaries/linux/yt-dlp
|
||||||
|
chmod +x resources/binaries/linux/ffmpeg
|
||||||
|
chmod +x resources/binaries/linux/ffprobe
|
||||||
|
chmod +x resources/binaries/linux/deno
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Notes
|
||||||
|
|
||||||
|
- These binaries are excluded from version control via `.gitignore`.
|
||||||
|
- Always use the latest stable release of each tool.
|
||||||
138
README.md
138
README.md
@@ -5,9 +5,9 @@
|
|||||||
alt="Banner"
|
alt="Banner"
|
||||||
style="width: 50%;"/></a>
|
style="width: 50%;"/></a>
|
||||||
|
|
||||||
### **A clean, open-source multimedia downloader for Windows**
|
### **A clean, open-source multimedia downloader for Windows and Linux**
|
||||||
|
|
||||||
[](https://github.com/MasterAcnolo/Freedom-Loader/releases)
|
[](https://github.com/MasterAcnolo/Freedom-Loader/releases)
|
||||||
[](https://www.gnu.org/licenses/gpl-3.0)
|
[](https://www.gnu.org/licenses/gpl-3.0)
|
||||||
[](https://masteracnolo.github.io/Freedom-Loader-Site/)
|
[](https://masteracnolo.github.io/Freedom-Loader-Site/)
|
||||||
[](https://masteracnolo.github.io/Freedom-Loader-Workshop/)
|
[](https://masteracnolo.github.io/Freedom-Loader-Workshop/)
|
||||||
@@ -86,35 +86,82 @@ The primary goal is to make media downloading accessible to users who want offli
|
|||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
|
[](https://copr.fedorainfracloud.org/coprs/masteracnolo/freedom-loader/)
|
||||||
|
[](https://github.com/MasterAcnolo/Freedom-Loader/releases)
|
||||||
|
[](https://snapcraft.io/freedom-loader)
|
||||||
|
[](https://github.com/MasterAcnolo/Freedom-Loader/releases)
|
||||||
|
|
||||||
### Requirements
|
### Requirements
|
||||||
|
|
||||||
- **Operating System**: Windows 10 or later
|
- **Windows**: Windows 10 or later
|
||||||
- **Browser**: Mozilla Firefox (required for cookie extraction)
|
- **Linux**: any modern x86_64 distribution
|
||||||
- [Download Firefox](https://www.firefox.com)
|
- **Browser**: Mozilla Firefox ([download](https://www.firefox.com)) required for cookie extraction, on both platforms
|
||||||
|
|
||||||
### Standard Installation
|
### Windows
|
||||||
|
|
||||||
1. Download the latest release from the [Releases page](https://github.com/MasterAcnolo/Freedom-Loader/releases)
|
1. Download the latest `.exe` from the [Releases page](https://github.com/MasterAcnolo/Freedom-Loader/releases)
|
||||||
2. Run the downloaded `.exe` installer
|
2. Run the installer (click "More info" → "Run anyway" if Windows Defender warns you)
|
||||||
3. If Windows Defender shows a warning, click "More info" then "Run anyway"
|
3. Follow the installation wizard
|
||||||
4. Follow the installation wizard
|
|
||||||
|
### Linux
|
||||||
|
|
||||||
|
#### Fedora (via Copr — recommended)
|
||||||
|
|
||||||
|
Installing via Copr lets `dnf` handle future updates automatically:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo dnf copr enable masteracnolo/freedom-loader
|
||||||
|
sudo dnf install freedom-loader
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Debian / Ubuntu (.deb)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Download the latest .deb from the Releases page, then:
|
||||||
|
sudo apt install ./freedom-loader_1.x.x_amd64.deb
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Snap (any distro with snapd)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo snap install freedom-loader
|
||||||
|
```
|
||||||
|
|
||||||
|
#### RPM (Fedora/RHEL/openSUSE, without Copr)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Download the latest .rpm from the Releases page, then:
|
||||||
|
sudo dnf install ./freedom-loader-1.x.y.x86_64.rpm
|
||||||
|
```
|
||||||
|
|
||||||
|
#### AppImage (any distro, no installation needed)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Download the latest .AppImage from the Releases page, then:
|
||||||
|
chmod +x Freedom-Loader-1.x.y.AppImage
|
||||||
|
./Freedom-Loader-1.x.y.AppImage
|
||||||
|
```
|
||||||
|
|
||||||
|
Once installed via any method, launch Freedom Loader from your application menu, or from a terminal with:
|
||||||
|
```bash
|
||||||
|
freedom-loader
|
||||||
|
```
|
||||||
|
|
||||||
### File Locations
|
### File Locations
|
||||||
|
|
||||||
Downloaded files are stored in:
|
| | Windows | Linux |
|
||||||
```
|
|---------------|---------------------------------------------------------|--------------------------------------|
|
||||||
C:\Users\[USERNAME]\Downloads\Freedom Loader
|
| **Downloads** | `C:\Users\[USERNAME]\Downloads\Freedom Loader` | `~/Downloads/Freedom Loader` |
|
||||||
```
|
| **Logs** | `C:\Users\[USERNAME]\AppData\Local\FreedomLoader\logs\` | `~/.local/share/FreedomLoader/logs/` |
|
||||||
> [!NOTE]
|
|
||||||
> *You can change it whenever you want. Just click the "Edit" button in the UI.*
|
|
||||||
|
|
||||||
Application logs can be found at:
|
> [!NOTE]
|
||||||
```
|
> The download folder can be changed anytime via the "Edit" button in the UI, on both platforms.
|
||||||
C:\Users\[USERNAME]\AppData\Local\FreedomLoader\logs\
|
|
||||||
```
|
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
|
> [!TIP]
|
||||||
|
> On Linux, you can start Freedom Loader using `freedom-loader` command
|
||||||
|
|
||||||
### Basic Download
|
### Basic Download
|
||||||
|
|
||||||
1. Launch Freedom Loader
|
1. Launch Freedom Loader
|
||||||
@@ -138,7 +185,7 @@ The application supports various configuration options:
|
|||||||
If you encounter issues:
|
If you encounter issues:
|
||||||
|
|
||||||
1. Restart the application
|
1. Restart the application
|
||||||
2. Check the logs in `AppData\Local\FreedomLoader\logs\`
|
2. Check the logs in `AppData\Local\FreedomLoader\logs\` or `~/.local/share/FreedomLoader/logs`
|
||||||
3. Open the developer console: `CTRL + SHIFT + I` → "Toggle Developer Tools"
|
3. Open the developer console: `CTRL + SHIFT + I` → "Toggle Developer Tools"
|
||||||
4. Create an issue on GitHub with logs and reproduction steps
|
4. Create an issue on GitHub with logs and reproduction steps
|
||||||
|
|
||||||
@@ -164,10 +211,17 @@ If you encounter issues:
|
|||||||
Freedom Loader can be configured either through the settings panel in the UI or by directly editing the `config.json` file located in the application data directory.
|
Freedom Loader can be configured either through the settings panel in the UI or by directly editing the `config.json` file located in the application data directory.
|
||||||
|
|
||||||
### Configuration File Location
|
### Configuration File Location
|
||||||
|
|
||||||
|
#### Windows
|
||||||
```
|
```
|
||||||
%APPDATA%\Freedom Loader\config.json
|
%APPDATA%\Freedom Loader\config.json
|
||||||
```
|
```
|
||||||
|
|
||||||
|
#### Linux
|
||||||
|
```
|
||||||
|
~/.config/Freedom Loader/config.json
|
||||||
|
```
|
||||||
|
|
||||||
### Available Options
|
### Available Options
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
@@ -192,24 +246,24 @@ Freedom Loader can be configured either through the settings panel in the UI or
|
|||||||
|
|
||||||
### Configuration Options
|
### Configuration Options
|
||||||
|
|
||||||
| Option | Type | Default | Description |
|
| Option | Type | Default | Description |
|
||||||
|--------|------|---------|-------------|
|
|------------------------------|---------|----------|------------------------------------------------------------|
|
||||||
| `autoUpdate` | boolean | `true` | Enable automatic application updates |
|
| `autoUpdate` | boolean | `true` | Enable automatic application updates |
|
||||||
| `discordRPC` | boolean | `true` | Enable Discord Rich Presence integration |
|
| `discordRPC` | boolean | `true` | Enable Discord Rich Presence integration |
|
||||||
| `customTopBar` | boolean | `true` | Use custom application top bar |
|
| `customTopBar` | boolean | `true` | Use custom application top bar |
|
||||||
| `autoCheckInfo` | boolean | `true` | Automatically fetch video information on URL paste |
|
| `autoCheckInfo` | boolean | `true` | Automatically fetch video information on URL paste |
|
||||||
| `addThumbnail` | boolean | `true` | Embed thumbnail in downloaded audio files |
|
| `addThumbnail` | boolean | `true` | Embed thumbnail in downloaded audio files |
|
||||||
| `addMetadata` | boolean | `true` | Add metadata tags to downloaded files |
|
| `addMetadata` | boolean | `true` | Add metadata tags to downloaded files |
|
||||||
| `verboseLogs` | boolean | `false` | Enable detailed logging for debugging |
|
| `verboseLogs` | boolean | `false` | Enable detailed logging for debugging |
|
||||||
| `autoDownloadPlaylist` | boolean | `true` | Automatically download entire playlists |
|
| `autoDownloadPlaylist` | boolean | `true` | Automatically download entire playlists |
|
||||||
| `createPlaylistFolders` | boolean | `true` | Automatically create a folder for a playlist |
|
| `createPlaylistFolders` | boolean | `true` | Automatically create a folder for a playlist |
|
||||||
| `customCodec` | string | `"h264"` | Video codec for encoding (supported: h264, h265, vp9, av1) |
|
| `customCodec` | string | `"h264"` | Video codec for encoding (supported: h264, h265, vp9, av1) |
|
||||||
| `logSystem` | boolean | `true` | Enable application logging |
|
| `logSystem` | boolean | `true` | Enable application logging |
|
||||||
| `outputTitleCheck` | boolean | `true` | Verify output file titles |
|
| `outputTitleCheck` | boolean | `true` | Verify output file titles |
|
||||||
| `downloadSystem` | boolean | `true` | Enable download system |
|
| `downloadSystem` | boolean | `true` | Enable download system |
|
||||||
| `notifySystem` | boolean | `true` | Enable system notifications |
|
| `notifySystem` | boolean | `true` | Enable system notifications |
|
||||||
| `enableHardwareAcceleration` | boolean | `true` | Enable Hardware Acceleration |
|
| `enableHardwareAcceleration` | boolean | `true` | Enable Hardware Acceleration |
|
||||||
| `theme` | string | `dark` | Current Theme Name |
|
| `theme` | string | `dark` | Current Theme Name |
|
||||||
|
|
||||||
### Supported Codecs
|
### Supported Codecs
|
||||||
|
|
||||||
@@ -423,7 +477,7 @@ resources/
|
|||||||
- Write clear commit messages
|
- Write clear commit messages
|
||||||
- Test thoroughly before submitting changes
|
- Test thoroughly before submitting changes
|
||||||
- Update documentation when adding features
|
- Update documentation when adding features
|
||||||
- Maintain compatibility with Windows 10+
|
- Maintain compatibility with Windows 10+ and Linux
|
||||||
|
|
||||||
## Roadmap
|
## Roadmap
|
||||||
|
|
||||||
@@ -445,7 +499,7 @@ Use the GitHub Issues system and include:
|
|||||||
- Clear description of the issue
|
- Clear description of the issue
|
||||||
- Steps to reproduce
|
- Steps to reproduce
|
||||||
- Expected vs actual behavior
|
- Expected vs actual behavior
|
||||||
- Relevant logs from `AppData\Local\FreedomLoader\logs\`
|
- Relevant logs from `AppData\Local\FreedomLoader\logs\` or `~/.local/share/FreedomLoader/logs/`
|
||||||
- Screenshots if applicable
|
- Screenshots if applicable
|
||||||
|
|
||||||
### Feature Requests
|
### Feature Requests
|
||||||
@@ -485,7 +539,7 @@ You are free to use, modify, and redistribute this software under the terms of t
|
|||||||
|
|
||||||
- [yt-dlp](https://github.com/yt-dlp/yt-dlp) for the robust download engine
|
- [yt-dlp](https://github.com/yt-dlp/yt-dlp) for the robust download engine
|
||||||
- [FFmpeg](https://ffmpeg.org/) for media processing capabilities
|
- [FFmpeg](https://ffmpeg.org/) for media processing capabilities
|
||||||
- [Deno](https://deno.com/) for helping me bypassing challenges
|
- [Deno](https://deno.com/) for helping me to bypass challenges
|
||||||
- [Electron](https://www.electronjs.org/) for the desktop application framework
|
- [Electron](https://www.electronjs.org/) for the desktop application framework
|
||||||
- The open-source community for continuous support and contributions
|
- The open-source community for continuous support and contributions
|
||||||
- [@SpicyFire21](https://github.com/SpicyFire21) to be the spiciest one
|
- [@SpicyFire21](https://github.com/SpicyFire21) to be the spiciest one
|
||||||
|
|||||||
73
SECURITY.md
73
SECURITY.md
@@ -2,15 +2,14 @@
|
|||||||
|
|
||||||
## Supported Versions
|
## Supported Versions
|
||||||
|
|
||||||
We actively maintain and provide security updates for the following versions of Freedom Loader:
|
Freedom Loader follows a **latest-only** support model. Security fixes are applied to the current release only — no backports to older versions.
|
||||||
|
|
||||||
| Version | Supported |
|
| Version | Supported |
|
||||||
|---------|--------------------|
|
| ------------- | ------------------ |
|
||||||
| 1.4.x | :white_check_mark: |
|
| Latest stable | :white_check_mark: |
|
||||||
| 1.3.x | :white_check_mark: |
|
| Older versions | :x: |
|
||||||
| < 1.3.0 | :x: |
|
|
||||||
|
|
||||||
**Note**: We recommend always using the latest version to benefit from the most recent security patches and features.
|
I recommend always running the latest version. The built-in auto-updater will notify you when a new release is available. Older versions will not receive security patches regardless of severity.
|
||||||
|
|
||||||
## Reporting a Vulnerability
|
## Reporting a Vulnerability
|
||||||
|
|
||||||
@@ -32,37 +31,40 @@ Instead, please report security issues privately by:
|
|||||||
|
|
||||||
### What to Expect
|
### What to Expect
|
||||||
|
|
||||||
- **Acknowledgment**: We will acknowledge receipt of your report within 48 hours
|
- **Acknowledgment**: I will acknowledge receipt of your report within 48 hours
|
||||||
- **Assessment**: We will assess the vulnerability and determine its severity
|
- **Assessment**: I will assess the vulnerability and determine its severity
|
||||||
- **Updates**: We will keep you informed of our progress
|
- **Updates**: I will keep you informed of our progress
|
||||||
- **Resolution**: We aim to release a fix within 7-14 days for critical vulnerabilities
|
- **Resolution**: I aim to release a fix within 7-14 days for critical vulnerabilities
|
||||||
- **Credit**: We will credit you in the release notes (unless you prefer to remain anonymous)
|
- **Credit**: I will credit you in the release notes (unless you prefer to remain anonymous)
|
||||||
|
|
||||||
## Security Best Practices for Users
|
## Security Best Practices for Users
|
||||||
|
|
||||||
When using Freedom Loader, we recommend:
|
When using Freedom Loader, I recommend:
|
||||||
|
|
||||||
### General Security
|
### General Security
|
||||||
|
|
||||||
- **Keep Updated**: Always use the latest version of Freedom Loader
|
- **Keep Updated**: Always use the latest version of Freedom Loader — older versions receive no security patches
|
||||||
- **Official Sources**: Download only from official releases on [GitHub](https://github.com/MasterAcnolo/Freedom-Loader/releases)
|
- **Official Sources**: Download only from official sources:
|
||||||
- **Verify Downloads**: Check that installers are properly signed (Windows SmartScreen may show warnings for new releases)
|
- [GitHub Releases](https://github.com/MasterAcnolo/Freedom-Loader/releases)
|
||||||
|
- [Fedora COPR](https://copr.fedorainfracloud.org/coprs/masteracnolo/freedom-loader/)
|
||||||
|
- [Snap Store](https://snapcraft.io/freedom-loader)
|
||||||
|
- **Verify Downloads**: Check that installers are from one of the above sources
|
||||||
- **Antivirus**: Keep your antivirus software up to date
|
- **Antivirus**: Keep your antivirus software up to date
|
||||||
|
|
||||||
### Configuration Security
|
### Configuration Security
|
||||||
|
|
||||||
- **Download Path**: Only set download paths within your user directory (`C:\Users\[USERNAME]\...`)
|
- **Download Path**: Only set download paths within your user directory
|
||||||
- **Cookies**: Be aware that Firefox cookies are used for authentication—keep Firefox secure
|
- **Cookies**: Be aware that Firefox cookies are used for authentication — keep Firefox secure
|
||||||
- **Logs**: Logs may contain sensitive information—avoid sharing them publicly without review
|
- **Logs**: Logs may contain sensitive information such as URLs or local paths — avoid sharing them publicly without review
|
||||||
|
|
||||||
### Privacy Considerations
|
### Privacy Considerations
|
||||||
|
|
||||||
Freedom Loader respects your privacy:
|
Freedom Loader respects your privacy:
|
||||||
|
|
||||||
- **No Data Collection**: We don't collect, store, or transmit your personal data
|
- **No Data Collection**: I don't collect, store, or transmit your personal data
|
||||||
- **No Telemetry**: No usage tracking or analytics
|
- **No Telemetry**: No usage tracking or analytics
|
||||||
- **Local Operation**: All downloads are processed locally on your machine
|
- **Local Operation**: All downloads are processed locally on your machine
|
||||||
- **Optional Features**: Discord RPC is optional and can be disabled
|
- **Optional Features**: Discord RPC is optional and can be disabled in settings
|
||||||
|
|
||||||
## Known Security Considerations
|
## Known Security Considerations
|
||||||
|
|
||||||
@@ -71,16 +73,16 @@ Freedom Loader respects your privacy:
|
|||||||
Freedom Loader accesses Firefox cookies to download protected content. This is:
|
Freedom Loader accesses Firefox cookies to download protected content. This is:
|
||||||
|
|
||||||
- **By Design**: Required for age-restricted or member-only content
|
- **By Design**: Required for age-restricted or member-only content
|
||||||
- **Local Only**: Cookies are read locally and never transmitted
|
- **Local Only**: Cookies are read locally and never transmitted outside your machine
|
||||||
- **User Controlled**: You can control what content you download
|
- **User Controlled**: You control what content you download
|
||||||
|
|
||||||
### Native Dependencies
|
### Native Dependencies
|
||||||
|
|
||||||
Freedom Loader bundles native binaries:
|
Freedom Loader bundles the following official binaries:
|
||||||
|
|
||||||
- **yt-dlp**: Official builds from [yt-dlp/yt-dlp](https://github.com/yt-dlp/yt-dlp)
|
- **yt-dlp**: Official builds from [yt-dlp/yt-dlp](https://github.com/yt-dlp/yt-dlp) — auto-updated on each launch
|
||||||
- **FFmpeg**: Official builds from [FFmpeg.org](https://ffmpeg.org/)
|
- **FFmpeg**: Official builds from [FFmpeg.org](https://ffmpeg.org/)
|
||||||
- **Deno**: Official builds from [Deno.land](https://deno.land/)
|
- **Deno**: Official builds from [Deno.com](https://deno.com/)
|
||||||
|
|
||||||
These dependencies are verified and updated regularly.
|
These dependencies are verified and updated regularly.
|
||||||
|
|
||||||
@@ -91,13 +93,13 @@ New releases may trigger Windows Defender warnings because:
|
|||||||
- The application is not yet widely distributed
|
- The application is not yet widely distributed
|
||||||
- Code signing certificates are expensive for open-source projects
|
- Code signing certificates are expensive for open-source projects
|
||||||
|
|
||||||
This is expected behavior for new releases. The warning will decrease as more users download the software.
|
This is expected behavior for new releases and will diminish as more users download the software.
|
||||||
|
|
||||||
## Vulnerability Disclosure Policy
|
## Vulnerability Disclosure Policy
|
||||||
|
|
||||||
### Our Commitment
|
### Our Commitment
|
||||||
|
|
||||||
We are committed to:
|
I am committed to:
|
||||||
|
|
||||||
- Responding promptly to security reports
|
- Responding promptly to security reports
|
||||||
- Working with security researchers to verify and address issues
|
- Working with security researchers to verify and address issues
|
||||||
@@ -107,9 +109,9 @@ We are committed to:
|
|||||||
### Disclosure Timeline
|
### Disclosure Timeline
|
||||||
|
|
||||||
1. **Day 0**: Vulnerability reported privately
|
1. **Day 0**: Vulnerability reported privately
|
||||||
2. **Day 1-2**: Acknowledgment sent to reporter
|
2. **Day 1–2**: Acknowledgment sent to reporter
|
||||||
3. **Day 3-7**: Vulnerability assessed and fix developed
|
3. **Day 3–7**: Vulnerability assessed and fix developed
|
||||||
4. **Day 7-14**: Fix released (critical vulnerabilities prioritized)
|
4. **Day 7–14**: Fix released (critical vulnerabilities prioritized)
|
||||||
5. **Day 14+**: Public disclosure (coordinated with reporter)
|
5. **Day 14+**: Public disclosure (coordinated with reporter)
|
||||||
|
|
||||||
### Scope
|
### Scope
|
||||||
@@ -129,16 +131,16 @@ The following are generally not considered security vulnerabilities:
|
|||||||
- Issues requiring physical access to the user's machine
|
- Issues requiring physical access to the user's machine
|
||||||
- Social engineering attacks
|
- Social engineering attacks
|
||||||
- Denial of service against third-party services
|
- Denial of service against third-party services
|
||||||
- Issues in third-party dependencies (report to upstream projects)
|
- Issues in third-party dependencies (report to upstream projects directly)
|
||||||
- Missing security headers on local HTTP server (no remote access)
|
- Missing security headers on the local HTTP server (not exposed remotely)
|
||||||
|
|
||||||
## Security Updates
|
## Security Updates
|
||||||
|
|
||||||
Security updates are released as:
|
Security updates are released as:
|
||||||
|
|
||||||
- **Patch Releases**: For critical security fixes (e.g., 1.4.1 → 1.4.2)
|
- **Patch Releases**: For critical security fixes (e.g., 1.6.0 → 1.6.1)
|
||||||
- **Automatic Updates**: Users are notified via the built-in update system
|
- **Automatic Updates**: Users are notified via the built-in update system
|
||||||
- **Release Notes**: Security fixes are clearly marked in changelog
|
- **Release Notes**: Security fixes are clearly marked in the changelog
|
||||||
|
|
||||||
## Additional Resources
|
## Additional Resources
|
||||||
|
|
||||||
@@ -150,6 +152,7 @@ Security updates are released as:
|
|||||||
|
|
||||||
For security-related questions or concerns:
|
For security-related questions or concerns:
|
||||||
|
|
||||||
|
- **Email**: masteracnolo25@gmail.com
|
||||||
- **GitHub**: [@MasterAcnolo](https://github.com/MasterAcnolo)
|
- **GitHub**: [@MasterAcnolo](https://github.com/MasterAcnolo)
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|||||||
@@ -96,8 +96,20 @@ function initAutoUpdater(mainWindow) {
|
|||||||
* Logs failure and displays an error dialog to user.
|
* Logs failure and displays an error dialog to user.
|
||||||
*/
|
*/
|
||||||
autoUpdater.on("error", (err) => {
|
autoUpdater.on("error", (err) => {
|
||||||
logger.error("Auto update error:", err.message);
|
const msg = err?.message || "";
|
||||||
dialog.showErrorBox("Update Error", err.message);
|
|
||||||
|
/**
|
||||||
|
* If no update is available, I put this because there is no Linux version before 1.6.0
|
||||||
|
* @type {boolean}
|
||||||
|
*/
|
||||||
|
const isNoUpdateAvailable = /404/.test(msg) || /Cannot find latest.*\.yml/i.test(msg);
|
||||||
|
|
||||||
|
if (isNoUpdateAvailable) {
|
||||||
|
logger.warn("Auto update: no update metadata found (probably no previous release), ignoring", msg);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.error("Auto update error:", msg);
|
||||||
});
|
});
|
||||||
|
|
||||||
checkForUpdates();
|
checkForUpdates();
|
||||||
@@ -109,6 +121,11 @@ function initAutoUpdater(mainWindow) {
|
|||||||
*/
|
*/
|
||||||
async function checkForUpdates() {
|
async function checkForUpdates() {
|
||||||
|
|
||||||
|
if (process.env.SNAP) {
|
||||||
|
logger.info("Running as Snap, update managed by snapd, skipping electron-updater");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (!require("electron").app.isPackaged) return ;
|
if (!require("electron").app.isPackaged) return ;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|||||||
18
main.js
18
main.js
@@ -37,7 +37,7 @@ app.setAppUserModelId("com.masteracnolo.freedomloader");
|
|||||||
/**
|
/**
|
||||||
* Load the app dependencies for hardware choice
|
* Load the app dependencies for hardware choice
|
||||||
*/
|
*/
|
||||||
const { logger, logSessionStart, logSessionEnd } = require("./server/logger");
|
const { logger, logSessionStart, logSessionEnd, logDir } = require("./server/logger");
|
||||||
const { configFeatures } = require("./config");
|
const { configFeatures } = require("./config");
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -79,7 +79,7 @@ const { updateYtDlp } = require("./app/ytDlpUpdater");
|
|||||||
const { createMainWindow, getMainWindow } = require("./app/windowManager");
|
const { createMainWindow, getMainWindow } = require("./app/windowManager");
|
||||||
const { registerIpcHandlers } = require("./app/ipcHandlers");
|
const { registerIpcHandlers } = require("./app/ipcHandlers");
|
||||||
const { createSplashWindow, closeSplashWindow, setSplashProgress } = require("./app/splashManager");
|
const { createSplashWindow, closeSplashWindow, setSplashProgress } = require("./app/splashManager");
|
||||||
const { userThemesPath, initUserThemes, isWindows } = require("./server/helpers/path.helpers");
|
const { userThemesPath, initUserThemes, isWindows, validateBinaries, defaultDownloadFolder } = require("./server/helpers/path.helpers");
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -99,7 +99,7 @@ app.on("second-instance", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
app.whenReady().then(async () => {
|
app.whenReady().then(async () => {
|
||||||
logSessionStart();
|
logSessionStart(logDir, defaultDownloadFolder);
|
||||||
|
|
||||||
createSplashWindow();
|
createSplashWindow();
|
||||||
|
|
||||||
@@ -117,14 +117,10 @@ app.whenReady().then(async () => {
|
|||||||
|
|
||||||
setSplashProgress(2); // Loading themes
|
setSplashProgress(2); // Loading themes
|
||||||
|
|
||||||
// TODO: Patch this, i disable this features for the moment
|
validateBinaries();
|
||||||
// Themes are currently disabled if we are not on Windows
|
|
||||||
if(isWindows){
|
initUserThemes();
|
||||||
initUserThemes();
|
await initThemes(userThemesPath);
|
||||||
await initThemes(userThemesPath);
|
|
||||||
} else {
|
|
||||||
logger.info(`OS is ${process.platform}, Skipping themes loading`)
|
|
||||||
}
|
|
||||||
|
|
||||||
setSplashProgress(3); // Almost ready
|
setSplashProgress(3); // Almost ready
|
||||||
await createMainWindow();
|
await createMainWindow();
|
||||||
|
|||||||
2203
package-lock.json
generated
2203
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
117
package.json
117
package.json
@@ -3,7 +3,16 @@
|
|||||||
"productName": "Freedom Loader",
|
"productName": "Freedom Loader",
|
||||||
"version": "1.6.0",
|
"version": "1.6.0",
|
||||||
"author": "MasterAcnolo <MasterAcnolo@users.noreply.github.com>",
|
"author": "MasterAcnolo <MasterAcnolo@users.noreply.github.com>",
|
||||||
"description": "Freedom Loader",
|
"description": "Free and open-source GUI for yt-dlp — download video and audio from hundreds of platforms",
|
||||||
|
"homepage": "https://masteracnolo.github.io/Freedom-Loader-Site/",
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/MasterAcnolo/Freedom-Loader.git"
|
||||||
|
},
|
||||||
|
"license": "GPL-3.0-only",
|
||||||
|
"bugs": {
|
||||||
|
"url": "https://github.com/MasterAcnolo/Freedom-Loader/issues"
|
||||||
|
},
|
||||||
"main": "main.js",
|
"main": "main.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"start": "electron --trace-warnings .",
|
"start": "electron --trace-warnings .",
|
||||||
@@ -11,6 +20,7 @@
|
|||||||
"build": "electron-builder",
|
"build": "electron-builder",
|
||||||
"build:win": "electron-builder --win",
|
"build:win": "electron-builder --win",
|
||||||
"build:linux": "electron-builder --linux",
|
"build:linux": "electron-builder --linux",
|
||||||
|
"build:rpm": "bash scripts/create-copr-package.sh",
|
||||||
"build:all": "electron-builder -wl",
|
"build:all": "electron-builder -wl",
|
||||||
"update": "npm update"
|
"update": "npm update"
|
||||||
},
|
},
|
||||||
@@ -27,9 +37,9 @@
|
|||||||
"winston-daily-rotate-file": "^5.0.0"
|
"winston-daily-rotate-file": "^5.0.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"@electron/devtron": "^2.1.1",
|
||||||
"electron": "^41.2.0",
|
"electron": "^41.2.0",
|
||||||
"electron-builder": "^26.8.1",
|
"electron-builder": "^25.1.8"
|
||||||
"@electron/devtron": "^2.1.1"
|
|
||||||
},
|
},
|
||||||
"build": {
|
"build": {
|
||||||
"appId": "com.masteracnolo.freedomloader",
|
"appId": "com.masteracnolo.freedomloader",
|
||||||
@@ -38,7 +48,8 @@
|
|||||||
{
|
{
|
||||||
"provider": "github",
|
"provider": "github",
|
||||||
"owner": "MasterAcnolo",
|
"owner": "MasterAcnolo",
|
||||||
"repo": "Freedom-Loader"
|
"repo": "Freedom-Loader",
|
||||||
|
"releaseType": "draft"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"files": [
|
"files": [
|
||||||
@@ -52,22 +63,52 @@
|
|||||||
},
|
},
|
||||||
"asar": true,
|
"asar": true,
|
||||||
"extraResources": [
|
"extraResources": [
|
||||||
{ "from": "theme", "to": "theme" },
|
{
|
||||||
{ "from": "build/confirm-icon.png", "to": "confirm-icon.png" },
|
"from": "theme",
|
||||||
{ "from": "build/banner.bmp", "to": "banner.bmp" },
|
"to": "theme"
|
||||||
{ "from": "build/banner.png", "to": "banner.png" },
|
},
|
||||||
{ "from": "build/error.png", "to": "error.png" },
|
{
|
||||||
{ "from": "config/config.default.json", "to": "config/config.default.json" }
|
"from": "build/confirm-icon.png",
|
||||||
|
"to": "confirm-icon.png"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"from": "build/banner.bmp",
|
||||||
|
"to": "banner.bmp"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"from": "build/banner.png",
|
||||||
|
"to": "banner.png"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"from": "build/error.png",
|
||||||
|
"to": "error.png"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"from": "config/config.default.json",
|
||||||
|
"to": "config/config.default.json"
|
||||||
|
}
|
||||||
],
|
],
|
||||||
"win": {
|
"win": {
|
||||||
"target": "nsis",
|
"target": "nsis",
|
||||||
"icon": "build/app-icon.ico",
|
"icon": "build/app-icon.ico",
|
||||||
"artifactName": "${productName}-Setup-${version}.${ext}",
|
"artifactName": "${productName}-Setup-${version}.${ext}",
|
||||||
"extraResources": [
|
"extraResources": [
|
||||||
{ "from": "resources/binaries/win-32/yt-dlp.exe", "to": "binaries/yt-dlp.exe" },
|
{
|
||||||
{ "from": "resources/binaries/win-32/ffmpeg.exe", "to": "binaries/ffmpeg.exe" },
|
"from": "resources/binaries/win-32/yt-dlp.exe",
|
||||||
{ "from": "resources/binaries/win-32/ffprobe.exe", "to": "binaries/ffprobe.exe" },
|
"to": "binaries/yt-dlp.exe"
|
||||||
{ "from": "resources/binaries/win-32/deno.exe", "to": "binaries/deno.exe" }
|
},
|
||||||
|
{
|
||||||
|
"from": "resources/binaries/win-32/ffmpeg.exe",
|
||||||
|
"to": "binaries/ffmpeg.exe"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"from": "resources/binaries/win-32/ffprobe.exe",
|
||||||
|
"to": "binaries/ffprobe.exe"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"from": "resources/binaries/win-32/deno.exe",
|
||||||
|
"to": "binaries/deno.exe"
|
||||||
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"nsis": {
|
"nsis": {
|
||||||
@@ -82,21 +123,49 @@
|
|||||||
"shortcutName": "Freedom Loader"
|
"shortcutName": "Freedom Loader"
|
||||||
},
|
},
|
||||||
"linux": {
|
"linux": {
|
||||||
"target": ["AppImage", "deb","rpm"],
|
"target": [
|
||||||
|
"AppImage",
|
||||||
|
"deb",
|
||||||
|
"snap"
|
||||||
|
],
|
||||||
"category": "Utility",
|
"category": "Utility",
|
||||||
"icon": "build/app-icon.png",
|
"icon": "build/app-icon.png",
|
||||||
|
"executableName": "freedom-loader",
|
||||||
"extraResources": [
|
"extraResources": [
|
||||||
{ "from": "resources/binaries/linux/yt-dlp", "to": "binaries/yt-dlp" },
|
|
||||||
{ "from": "resources/binaries/linux/ffmpeg", "to": "binaries/ffmpeg" },
|
|
||||||
{ "from": "resources/binaries/linux/ffprobe", "to": "binaries/ffprobe" },
|
|
||||||
{ "from": "resources/binaries/linux/deno", "to": "binaries/deno" }
|
|
||||||
],
|
|
||||||
"extraFiles": [
|
|
||||||
{
|
{
|
||||||
"from": "package/com.masteracnolo.freedomloader.metainfo.xml",
|
"from": "resources/binaries/linux/yt-dlp",
|
||||||
"to": "usr/share/metainfo/com.masteracnolo.freedomloader.metainfo.xml"
|
"to": "binaries/yt-dlp"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"from": "resources/binaries/linux/ffmpeg",
|
||||||
|
"to": "binaries/ffmpeg"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"from": "resources/binaries/linux/ffprobe",
|
||||||
|
"to": "binaries/ffprobe"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"from": "resources/binaries/linux/deno",
|
||||||
|
"to": "binaries/deno"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
},
|
||||||
|
"deb": {
|
||||||
|
"fpm": [
|
||||||
|
"./package/com.masteracnolo.freedomloader.metainfo.xml=/usr/share/metainfo/com.masteracnolo.freedomloader.metainfo.xml"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"rpm": {
|
||||||
|
"fpm": [
|
||||||
|
"./package/com.masteracnolo.freedomloader.metainfo.xml=/usr/share/metainfo/com.masteracnolo.freedomloader.metainfo.xml"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"snap": {
|
||||||
|
"confinement": "strict",
|
||||||
|
"plugs": [
|
||||||
|
"default",
|
||||||
|
"removable-media"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
73
package/com.masteracnolo.freedomloader.metainfo.xml
Normal file
73
package/com.masteracnolo.freedomloader.metainfo.xml
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
|
||||||
|
<component type="desktop-application">
|
||||||
|
<id>com.masteracnolo.freedomloader</id>
|
||||||
|
|
||||||
|
<name>Freedom Loader</name>
|
||||||
|
|
||||||
|
<summary>GUI for yt-dlp to download video and audio with metadata</summary>
|
||||||
|
|
||||||
|
<metadata_license>CC0-1.0</metadata_license>
|
||||||
|
<project_license>GPL-3.0-only</project_license>
|
||||||
|
|
||||||
|
<developer id="com.masteracnolo">
|
||||||
|
<name>MasterAcnolo</name>
|
||||||
|
</developer>
|
||||||
|
|
||||||
|
<description>
|
||||||
|
<p>
|
||||||
|
Freedom Loader is a free and open-source graphical interface built
|
||||||
|
around yt-dlp, the powerful command-line media downloader. It lets
|
||||||
|
you download video and audio from hundreds of supported websites
|
||||||
|
without ever touching a terminal, with no ads, no tracking, and
|
||||||
|
no questionable third-party services.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Under the hood, Freedom Loader bundles yt-dlp and ffmpeg directly,
|
||||||
|
so there is nothing extra to install: paste a link, choose a
|
||||||
|
format and quality, and the app handles fetching, converting
|
||||||
|
and tagging the file for you.
|
||||||
|
</p>
|
||||||
|
<p>Features include:</p>
|
||||||
|
<ul>
|
||||||
|
<li>MP4 video or MP3 audio downloads with embedded metadata and thumbnails</li>
|
||||||
|
<li>Quality selection from best to specific resolutions (1080p, 720p, 480p)</li>
|
||||||
|
<li>Codec choice: H.264, H.265, AV1, VP9 and Theora</li>
|
||||||
|
<li>Playlist downloads with automatic per-playlist folders</li>
|
||||||
|
<li>Cookie-based access to age-restricted and member-only content</li>
|
||||||
|
<li>Custom theme system with a web-based theme creator</li>
|
||||||
|
<li>Real-time download progress with network speed indicator</li>
|
||||||
|
<li>Optional Discord Rich Presence integration</li>
|
||||||
|
<li>Automatic application and download-engine updates</li>
|
||||||
|
</ul>
|
||||||
|
<p>
|
||||||
|
DRM-protected content is not supported and cannot be downloaded.
|
||||||
|
</p>
|
||||||
|
</description>
|
||||||
|
|
||||||
|
<launchable type="desktop-id">freedom-loader.desktop</launchable>
|
||||||
|
|
||||||
|
<url type="homepage">https://github.com/MasterAcnolo/Freedom-Loader</url>
|
||||||
|
<url type="bugtracker">https://github.com/MasterAcnolo/Freedom-Loader/issues</url>
|
||||||
|
<url type="vcs-browser">https://github.com/MasterAcnolo/Freedom-Loader</url>
|
||||||
|
|
||||||
|
<categories>
|
||||||
|
<category>AudioVideo</category>
|
||||||
|
<category>Utility</category>
|
||||||
|
<category>Network</category>
|
||||||
|
</categories>
|
||||||
|
|
||||||
|
<releases>
|
||||||
|
<release version="1.6.0" date="2026-06-23">
|
||||||
|
<description>
|
||||||
|
<p>Latest stable release.</p>
|
||||||
|
</description>
|
||||||
|
</release>
|
||||||
|
</releases>
|
||||||
|
|
||||||
|
<content_rating type="oars-1.1"/>
|
||||||
|
|
||||||
|
<provides>
|
||||||
|
<binary>freedom-loader</binary>
|
||||||
|
</provides>
|
||||||
|
</component>
|
||||||
9
package/copr-build.sh
Normal file
9
package/copr-build.sh
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
#!/bin/sh -xe
|
||||||
|
git clone --depth 1 https://github.com/MasterAcnolo/Freedom-Loader.git src
|
||||||
|
cd src
|
||||||
|
npm ci
|
||||||
|
npx electron-builder --linux dir
|
||||||
|
|
||||||
|
VERSION=$(node -p "require('./package.json').version")
|
||||||
|
tar czf "$resultdir/freedom-loader-$VERSION.tar.gz" -C dist linux-unpacked
|
||||||
|
sed "s/__VERSION__/$VERSION/" package/freedom-loader.spec > "$resultdir/freedom-loader.spec"
|
||||||
25
package/freedom-loader.spec
Normal file
25
package/freedom-loader.spec
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
Name: freedom-loader
|
||||||
|
Version: __VERSION__
|
||||||
|
Release: 1%{?dist}
|
||||||
|
Summary: GUI for yt-dlp media downloads
|
||||||
|
License: GPL-3.0-only
|
||||||
|
Source0: freedom-loader-__VERSION__.x86_64.rpm
|
||||||
|
BuildArch: x86_64
|
||||||
|
Requires: glibc, gtk3, nss, libXScrnSaver
|
||||||
|
|
||||||
|
%description
|
||||||
|
GUI for yt-dlp media downloads.
|
||||||
|
|
||||||
|
%install
|
||||||
|
rpm2cpio %{SOURCE0} | (cd %{buildroot} && cpio -idmv)
|
||||||
|
mkdir -p %{buildroot}/usr/bin
|
||||||
|
ln -sf "/opt/Freedom Loader/freedom-loader" %{buildroot}/usr/bin/freedom-loader
|
||||||
|
|
||||||
|
%files
|
||||||
|
/opt/*
|
||||||
|
/usr/bin/freedom-loader
|
||||||
|
/usr/share/applications/*
|
||||||
|
/usr/share/metainfo/*
|
||||||
|
/usr/share/icons/hicolor
|
||||||
|
|
||||||
|
%changelog
|
||||||
@@ -25,6 +25,3 @@ async function initPlatformRestrictions() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
document.addEventListener('DOMContentLoaded', function(){
|
|
||||||
initPlatformRestrictions();
|
|
||||||
})
|
|
||||||
Binary file not shown.
50
scripts/create-copr-package.sh
Executable file
50
scripts/create-copr-package.sh
Executable file
@@ -0,0 +1,50 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
set -e
|
||||||
|
|
||||||
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
|
ROOT_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
|
||||||
|
VERSION=$(node -p "require('$ROOT_DIR/package.json').version")
|
||||||
|
RPM_OUT="$ROOT_DIR/dist/freedom-loader-${VERSION}.x86_64.rpm"
|
||||||
|
|
||||||
|
# Check that linux-unpacked exists
|
||||||
|
if [ ! -d "$ROOT_DIR/dist/linux-unpacked" ]; then
|
||||||
|
echo "Error: dist/linux-unpacked not found. Run 'npm run build:linux' first."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Step 1 — Build .rpm from linux-unpacked via fpm
|
||||||
|
echo "Building RPM..."
|
||||||
|
fpm -s dir -t rpm --force \
|
||||||
|
--name freedom-loader \
|
||||||
|
--version "$VERSION" \
|
||||||
|
--architecture x86_64 \
|
||||||
|
--description "Free and open-source GUI for yt-dlp" \
|
||||||
|
--url "https://masteracnolo.github.io/Freedom-Loader-Site/" \
|
||||||
|
--maintainer "MasterAcnolo <MasterAcnolo@users.noreply.github.com>" \
|
||||||
|
--license "GPL-3.0-only" \
|
||||||
|
--depends gtk3 \
|
||||||
|
--depends nss \
|
||||||
|
--depends libXScrnSaver \
|
||||||
|
--depends at-spi2-core \
|
||||||
|
--package "$RPM_OUT" \
|
||||||
|
"$ROOT_DIR/dist/linux-unpacked/=/opt/freedom-loader" \
|
||||||
|
"$ROOT_DIR/build/app-icon.png=/usr/share/icons/hicolor/512x512/apps/freedom-loader.png" \
|
||||||
|
"$ROOT_DIR/package/com.masteracnolo.freedomloader.metainfo.xml=/usr/share/metainfo/com.masteracnolo.freedomloader.metainfo.xml"
|
||||||
|
|
||||||
|
echo "RPM built: $RPM_OUT"
|
||||||
|
|
||||||
|
# Step 2 — Build SRPM for COPR (wraps the .rpm above)
|
||||||
|
echo "Building SRPM for COPR..."
|
||||||
|
mkdir -p "$ROOT_DIR/srpm-out"
|
||||||
|
|
||||||
|
TMP_DIR="$ROOT_DIR/.copr-build-tmp"
|
||||||
|
mkdir -p "$TMP_DIR"
|
||||||
|
TMP_SPEC="$TMP_DIR/freedom-loader.spec"
|
||||||
|
sed "s/__VERSION__/$VERSION/g" "$ROOT_DIR/package/freedom-loader.spec" > "$TMP_SPEC"
|
||||||
|
|
||||||
|
rpmbuild -bs "$TMP_SPEC" \
|
||||||
|
--define "_sourcedir $ROOT_DIR/dist" \
|
||||||
|
--define "_srcrpmdir $ROOT_DIR/srpm-out"
|
||||||
|
|
||||||
|
rm -rf "$TMP_DIR"
|
||||||
|
echo "SRPM built: $ROOT_DIR/srpm-out/freedom-loader-$VERSION-1*.src.rpm"
|
||||||
@@ -3,8 +3,6 @@ const fs = require("fs");
|
|||||||
const { app } = require("electron");
|
const { app } = require("electron");
|
||||||
const config = require("../../config.js");
|
const config = require("../../config.js");
|
||||||
|
|
||||||
const { logger } = require("../logger.js");
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Is the OS windows
|
* Is the OS windows
|
||||||
*/
|
*/
|
||||||
@@ -104,7 +102,7 @@ if (config.devMode) {
|
|||||||
try {
|
try {
|
||||||
fs.chmodSync(userYtDlp, 0o755);
|
fs.chmodSync(userYtDlp, 0o755);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
logger.warn(`Failed to chmod yt-dlp: ${err.message}`);
|
getLogger().warn(`Failed to chmod yt-dlp: ${err.message}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -165,48 +163,48 @@ function initUserThemes() {
|
|||||||
try {
|
try {
|
||||||
if (!fs.existsSync(userThemesPath)) {
|
if (!fs.existsSync(userThemesPath)) {
|
||||||
fs.mkdirSync(userThemesPath, { recursive: true });
|
fs.mkdirSync(userThemesPath, { recursive: true });
|
||||||
// Ensure folder is writable
|
|
||||||
fs.chmodSync(userThemesPath, 0o777);
|
fs.chmodSync(userThemesPath, 0o777);
|
||||||
logger.info("Created user themes directory");
|
getLogger().info("Created user themes directory");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Copy default themes from resources to user directory if they don't exist
|
|
||||||
if (fs.existsSync(defaultThemesSourcePath)) {
|
if (fs.existsSync(defaultThemesSourcePath)) {
|
||||||
const defaultThemes = fs.readdirSync(defaultThemesSourcePath);
|
const defaultThemes = fs.readdirSync(defaultThemesSourcePath);
|
||||||
for (const theme of defaultThemes) {
|
for (const theme of defaultThemes) {
|
||||||
const srcPath = path.join(defaultThemesSourcePath, theme);
|
const srcPath = path.join(defaultThemesSourcePath, theme);
|
||||||
const destPath = path.join(userThemesPath, theme);
|
const destPath = path.join(userThemesPath, theme);
|
||||||
if (!fs.existsSync(destPath)) {
|
const srcIsFile = !fs.statSync(srcPath).isDirectory();
|
||||||
try {
|
|
||||||
|
if (fs.existsSync(destPath)) {
|
||||||
|
const destIsDir = fs.statSync(destPath).isDirectory();
|
||||||
|
if (srcIsFile && destIsDir) {
|
||||||
|
getLogger().warn(`Corrupted theme entry: ${theme}, fixing...`);
|
||||||
|
fs.rmSync(destPath, { recursive: true, force: true });
|
||||||
|
|
||||||
|
} else {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (srcIsFile) {
|
||||||
|
fs.copyFileSync(srcPath, destPath);
|
||||||
|
fs.chmodSync(destPath, 0o666);
|
||||||
|
} else {
|
||||||
copyDirectory(srcPath, destPath);
|
copyDirectory(srcPath, destPath);
|
||||||
fs.chmodSync(destPath, 0o777);
|
fs.chmodSync(destPath, 0o777);
|
||||||
logger.info(`Copied default theme: ${theme}`);
|
|
||||||
} catch (copyErr) {
|
|
||||||
logger.warn(
|
|
||||||
`Failed to copy theme ${theme}: ${copyErr.message}. Theme folder will be created, add theme files manually.`
|
|
||||||
);
|
|
||||||
|
|
||||||
try {
|
|
||||||
fs.mkdirSync(destPath, { recursive: true });
|
|
||||||
fs.chmodSync(destPath, 0o777);
|
|
||||||
} catch (mkdirErr) {
|
|
||||||
logger.warn(
|
|
||||||
`Could not create theme directory ${theme}: ${mkdirErr.message}`
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
getLogger().info(`Copied default theme: ${theme}`);
|
||||||
|
} catch (copyErr) {
|
||||||
|
getLogger().warn(`Failed to copy theme ${theme}: ${copyErr.message}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
logger.warn(
|
getLogger().warn(`Default themes source path not found: ${defaultThemesSourcePath}`);
|
||||||
`Default themes source path not found: ${defaultThemesSourcePath}`
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
logger.error(`Failed to initialize user themes: ${err.message}`);
|
getLogger().error(`Failed to initialize user themes: ${err.message}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Recursively copies a directory and its contents.
|
* Recursively copies a directory and its contents.
|
||||||
*
|
*
|
||||||
@@ -241,16 +239,31 @@ function copyDirectory(src, dest) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Runtime validation of critical binaries
|
// Runtime validation of critical binaries
|
||||||
if (!userYtDlp) {
|
// if (!userYtDlp) {
|
||||||
logger.error("Missing yt-dlp binary");
|
// getLogger().error("Missing yt-dlp binary");
|
||||||
|
// }
|
||||||
|
|
||||||
|
// if (!ffmpegPath) {
|
||||||
|
// getLogger().error("Missing ffmpeg binary");
|
||||||
|
// }
|
||||||
|
|
||||||
|
// if (!denoPath) {
|
||||||
|
// getLogger().error("Missing deno binary");
|
||||||
|
// }
|
||||||
|
|
||||||
|
|
||||||
|
function validateBinaries() {
|
||||||
|
if (!userYtDlp) getLogger().error("Missing yt-dlp binary");
|
||||||
|
if (!ffmpegPath) getLogger().error("Missing ffmpeg binary");
|
||||||
|
if (!denoPath) getLogger().error("Missing deno binary");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ffmpegPath) {
|
/**
|
||||||
logger.error("Missing ffmpeg binary");
|
* Helper to lazy load logger, avoid circular import
|
||||||
|
* @returns {winston.Logger}
|
||||||
|
*/
|
||||||
|
function getLogger() {
|
||||||
|
return require("../logger.js").logger;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!denoPath) {
|
module.exports = { userYtDlp, ffmpegPath, denoPath, iconPaths, binaryPaths, resourcesPath, defaultDownloadFolder, userThemesPath, initUserThemes, isWindows, validateBinaries };
|
||||||
logger.error("Missing deno binary");
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = { userYtDlp, ffmpegPath, denoPath, iconPaths, binaryPaths, resourcesPath, defaultDownloadFolder, userThemesPath, initUserThemes, isWindows };
|
|
||||||
@@ -5,6 +5,7 @@ const path = require("path");
|
|||||||
const os = require("os");
|
const os = require("os");
|
||||||
const config = require("../config");
|
const config = require("../config");
|
||||||
const {isWindows} = require("./helpers/path.helpers");
|
const {isWindows} = require("./helpers/path.helpers");
|
||||||
|
const { logSystemInfo } = require("./sysinfo");
|
||||||
|
|
||||||
// Logs folder in Windows
|
// Logs folder in Windows
|
||||||
const logDir = isWindows ? path.join(os.homedir(), "AppData", "Local", "FreedomLoader", "logs") : path.join(process.env.XDG_DATA_HOME || path.join(os.homedir(), ".local", "share"), "FreedomLoader", "logs");
|
const logDir = isWindows ? path.join(os.homedir(), "AppData", "Local", "FreedomLoader", "logs") : path.join(process.env.XDG_DATA_HOME || path.join(os.homedir(), ".local", "share"), "FreedomLoader", "logs");
|
||||||
@@ -52,9 +53,10 @@ const logger = createLogger({
|
|||||||
/**
|
/**
|
||||||
* Start Log Session
|
* Start Log Session
|
||||||
*/
|
*/
|
||||||
function logSessionStart() {
|
function logSessionStart(logDir, downloadPath) {
|
||||||
logger.info(`--- Starting session: ${new Date().toISOString()} ---`);
|
logger.info(`--- Starting session: ${new Date().toISOString()} ---`);
|
||||||
logger.info(`Application Version: ${config.version}`)
|
logger.info(`Application Version: ${config.version}`)
|
||||||
|
logSystemInfo(logger, logDir, downloadPath)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
142
server/sysinfo.js
Normal file
142
server/sysinfo.js
Normal file
@@ -0,0 +1,142 @@
|
|||||||
|
const os = require("os");
|
||||||
|
const fs = require("fs");
|
||||||
|
const { execSync } = require("child_process");
|
||||||
|
const { app } = require("electron");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads /etc/os-release to get the Linux distribution name
|
||||||
|
*/
|
||||||
|
function getLinuxDistro() {
|
||||||
|
try {
|
||||||
|
const content = fs.readFileSync("/etc/os-release", "utf-8");
|
||||||
|
const pretty = content.match(/^PRETTY_NAME="?(.+?)"?$/m);
|
||||||
|
if (pretty) return pretty[1];
|
||||||
|
const name = content.match(/^NAME="?(.+?)"?$/m);
|
||||||
|
return name ? name[1] : "Unknown Linux";
|
||||||
|
} catch {
|
||||||
|
return "Unknown Linux";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads the package-type file written by electron-builder
|
||||||
|
* to determine how the app was distributed (rpm, snap, AppImage, deb...)
|
||||||
|
*/
|
||||||
|
function getPackageType() {
|
||||||
|
try {
|
||||||
|
const pkgTypePath = require("path").join(process.resourcesPath, "package-type");
|
||||||
|
if (fs.existsSync(pkgTypePath)) {
|
||||||
|
return fs.readFileSync(pkgTypePath, "utf-8").trim();
|
||||||
|
}
|
||||||
|
} catch { /* ignore */ }
|
||||||
|
return "unknown";
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if Firefox is installed on the current platform
|
||||||
|
*/
|
||||||
|
function detectFirefox() {
|
||||||
|
const platform = process.platform;
|
||||||
|
|
||||||
|
if (platform === "win32") {
|
||||||
|
const paths = [
|
||||||
|
"C:\\Program Files\\Mozilla Firefox\\firefox.exe",
|
||||||
|
"C:\\Program Files (x86)\\Mozilla Firefox\\firefox.exe",
|
||||||
|
`${process.env.LOCALAPPDATA}\\Mozilla Firefox\\firefox.exe`,
|
||||||
|
];
|
||||||
|
return paths.some(p => fs.existsSync(p));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (platform === "linux") {
|
||||||
|
const paths = [
|
||||||
|
"/usr/bin/firefox",
|
||||||
|
"/usr/bin/firefox-esr",
|
||||||
|
"/usr/local/bin/firefox",
|
||||||
|
"/snap/bin/firefox",
|
||||||
|
"/var/lib/flatpak/exports/bin/org.mozilla.firefox",
|
||||||
|
`${os.homedir()}/.local/share/flatpak/exports/bin/org.mozilla.firefox`,
|
||||||
|
];
|
||||||
|
if (paths.some(p => fs.existsSync(p))) return true;
|
||||||
|
try { execSync("which firefox", { stdio: "ignore" }); return true; } catch { return false; }
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Builds the system info object logged at startup
|
||||||
|
*
|
||||||
|
* @param {string} logDir - path to the log directory
|
||||||
|
* @param {string} downloadPath - current configured download path
|
||||||
|
*/
|
||||||
|
function getSystemInfo(logDir, downloadPath) {
|
||||||
|
const platform = process.platform;
|
||||||
|
const cpus = os.cpus();
|
||||||
|
const totalMem = (os.totalmem() / 1024 / 1024 / 1024).toFixed(1);
|
||||||
|
const freeMem = (os.freemem() / 1024 / 1024 / 1024).toFixed(1);
|
||||||
|
|
||||||
|
let platformLabel;
|
||||||
|
if (platform === "win32") {
|
||||||
|
platformLabel = `Windows (${os.release()})`;
|
||||||
|
} else if (platform === "linux") {
|
||||||
|
platformLabel = `Linux — ${getLinuxDistro()}`;
|
||||||
|
} else {
|
||||||
|
platformLabel = `${platform} ${os.release()} (unsupported)`;
|
||||||
|
}
|
||||||
|
|
||||||
|
const info = {
|
||||||
|
"Platform": platformLabel,
|
||||||
|
"Architecture": os.arch(),
|
||||||
|
"CPU": cpus.length ? `${cpus[0].model.trim()} (${cpus.length} cores)` : "Unknown",
|
||||||
|
"Memory": `${freeMem} GB free / ${totalMem} GB total`,
|
||||||
|
"Locale": app.getLocale(),
|
||||||
|
"Electron": process.versions.electron,
|
||||||
|
"Node": process.versions.node,
|
||||||
|
"Packaged": String(app.isPackaged),
|
||||||
|
"Package type": app.isPackaged ? getPackageType() : "dev",
|
||||||
|
"Firefox present": detectFirefox() ? "Yes" : "No — cookie features unavailable",
|
||||||
|
"Log directory": logDir,
|
||||||
|
"Download path": downloadPath,
|
||||||
|
};
|
||||||
|
|
||||||
|
// Linux-specific extras
|
||||||
|
if (platform === "linux") {
|
||||||
|
const sessionType = process.env.XDG_SESSION_TYPE || "unknown";
|
||||||
|
const waylandDisplay = process.env.WAYLAND_DISPLAY;
|
||||||
|
const x11Display = process.env.DISPLAY;
|
||||||
|
|
||||||
|
info["Display server"] = waylandDisplay
|
||||||
|
? `Wayland (${waylandDisplay})`
|
||||||
|
: x11Display
|
||||||
|
? `X11 (${x11Display})`
|
||||||
|
: sessionType !== "unknown"
|
||||||
|
? sessionType
|
||||||
|
: "unknown";
|
||||||
|
|
||||||
|
info["Desktop env"] = process.env.XDG_CURRENT_DESKTOP || process.env.DESKTOP_SESSION || "unknown";
|
||||||
|
}
|
||||||
|
|
||||||
|
return info;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Logs system info at application startup
|
||||||
|
*
|
||||||
|
* @param {object} logger - winston logger instance
|
||||||
|
* @param {string} logDir - path to the log directory
|
||||||
|
* @param {string} downloadPath - current configured download path
|
||||||
|
*/
|
||||||
|
function logSystemInfo(logger, logDir, downloadPath) {
|
||||||
|
const info = getSystemInfo(logDir, downloadPath);
|
||||||
|
const maxKeyLen = Math.max(...Object.keys(info).map(k => k.length));
|
||||||
|
|
||||||
|
logger.info("=".repeat(60));
|
||||||
|
logger.info("SYSTEM INFO");
|
||||||
|
logger.info("=".repeat(60));
|
||||||
|
for (const [key, val] of Object.entries(info)) {
|
||||||
|
logger.info(` ${key.padEnd(maxKeyLen)} : ${val}`);
|
||||||
|
}
|
||||||
|
logger.info("=".repeat(60));
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = { logSystemInfo };
|
||||||
Reference in New Issue
Block a user