Compare commits

...

35 Commits

Author SHA1 Message Date
KeksNino ba4321b892 update github CI workflow 2026-07-11 00:03:54 +02:00
KeksNino a8f0186c2e re-enable appimage build step 2026-07-10 23:57:39 +02:00
KeksNino 1574ae594e fix github CI 2026-07-10 23:42:28 +02:00
KeksNino 2b45038a62 testing... 2026-07-10 23:40:41 +02:00
KeksNino 727d31fbcc fix stage artifact step in github CI 2026-07-10 23:32:28 +02:00
KeksNino 710ef26151 add appimage build step to github CI 2026-07-10 23:27:11 +02:00
KeksNino fdd8aa81ba add appimage build script (credits to OnTheSpot) 2026-07-10 23:21:09 +02:00
KeksNino a4c6c3381a install system dependencies on linux in CI workflow 2026-07-10 16:36:19 +02:00
Vxrtrauter 68a9e870cf feat: implement middleware for VST Search subdomain HTML rewriting 2026-07-06 23:25:52 +02:00
Vxrtrauter 02de32719d Merge branch 'main' of https://github.com/KeksPirates/SoftwareManager 2026-07-06 23:20:54 +02:00
Vxrtrauter c5a78a2da3 feat: add VST middleware for dynamic HTML content rewriting 2026-07-06 23:20:51 +02:00
shayaa 32f02d856d Merge pull request #104 from KeksPirates/feat-website-vstsearch
Add VST search functionality
2026-07-06 23:12:36 +02:00
Vxrtrauter 4edb1baa0b add vst search 2026-07-06 23:11:18 +02:00
shayaa 1ffa1cacb9 Merge pull request #99 from KeksPirates/auto/sync-readme-dependencies
Sync README dependencies
2026-05-14 23:36:19 +02:00
Vxrtrauter 207eb70f11 Sync README dependencies 2026-05-14 21:10:34 +00:00
shayaa 64144e5ed7 Merge pull request #98 from KeksPirates/dependabot/pip/requests-2.34.2
build(deps): bump requests from 2.34.1 to 2.34.2
2026-05-14 23:10:21 +02:00
dependabot[bot] d05fae7e87 build(deps): bump requests from 2.34.1 to 2.34.2
Bumps [requests](https://github.com/psf/requests) from 2.34.1 to 2.34.2.
- [Release notes](https://github.com/psf/requests/releases)
- [Changelog](https://github.com/psf/requests/blob/main/HISTORY.md)
- [Commits](https://github.com/psf/requests/compare/v2.34.1...v2.34.2)

---
updated-dependencies:
- dependency-name: requests
  dependency-version: 2.34.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-05-14 19:37:56 +00:00
shayaa 9abdec6c33 Merge pull request #97 from KeksPirates/auto/sync-readme-dependencies
Sync README dependencies
2026-05-13 22:08:47 +02:00
Vxrtrauter fb5eb61d05 Sync README dependencies 2026-05-13 20:07:34 +00:00
shayaa eff2164ecc Merge pull request #89 from KeksPirates/dependabot/pip/pyinstaller-6.20.0
build(deps): bump pyinstaller from 6.19.0 to 6.20.0
2026-05-13 22:07:23 +02:00
shayaa d8aa206ea2 Merge pull request #94 from KeksPirates/dependabot/pip/pyside6-essentials-6.11.1
build(deps): bump pyside6-essentials from 6.11.0 to 6.11.1
2026-05-13 22:07:00 +02:00
dependabot[bot] 6de74303ff build(deps): bump pyside6-essentials from 6.11.0 to 6.11.1
Bumps [pyside6-essentials](https://pyside.org) from 6.11.0 to 6.11.1.

---
updated-dependencies:
- dependency-name: pyside6-essentials
  dependency-version: 6.11.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-05-13 20:06:46 +00:00
shayaa 5eb6314cb2 Merge pull request #96 from KeksPirates/auto/sync-readme-dependencies
Sync README dependencies
2026-05-13 22:05:49 +02:00
Vxrtrauter 179dd0af83 Sync README dependencies 2026-05-13 20:05:32 +00:00
shayaa 365700900f Merge pull request #95 from KeksPirates/dependabot/pip/requests-2.34.1
build(deps): bump requests from 2.34.0 to 2.34.1
2026-05-13 22:05:03 +02:00
dependabot[bot] babbccdc9a build(deps): bump requests from 2.34.0 to 2.34.1
Bumps [requests](https://github.com/psf/requests) from 2.34.0 to 2.34.1.
- [Release notes](https://github.com/psf/requests/releases)
- [Changelog](https://github.com/psf/requests/blob/main/HISTORY.md)
- [Commits](https://github.com/psf/requests/compare/v2.34.0...v2.34.1)

---
updated-dependencies:
- dependency-name: requests
  dependency-version: 2.34.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-05-13 19:47:10 +00:00
shayaa 367ffab86a Merge pull request #93 from KeksPirates/auto/sync-readme-dependencies
Sync README dependencies
2026-05-12 10:57:57 +02:00
Vxrtrauter 71bad60617 Sync README dependencies 2026-05-12 08:46:59 +00:00
shayaa 27758f794c Merge pull request #92 from KeksPirates/dependabot/pip/requests-2.34.0
build(deps): bump requests from 2.33.1 to 2.34.0
2026-05-12 10:46:50 +02:00
dependabot[bot] d82afe8577 build(deps): bump requests from 2.33.1 to 2.34.0
Bumps [requests](https://github.com/psf/requests) from 2.33.1 to 2.34.0.
- [Release notes](https://github.com/psf/requests/releases)
- [Changelog](https://github.com/psf/requests/blob/main/HISTORY.md)
- [Commits](https://github.com/psf/requests/compare/v2.33.1...v2.34.0)

---
updated-dependencies:
- dependency-name: requests
  dependency-version: 2.34.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-05-12 02:25:02 +00:00
Vxrtrauter 8592b3058e Merge branch 'main' of https://github.com/KeksPirates/SoftwareManager 2026-05-04 21:51:20 +02:00
Vxrtrauter 7a82e948b9 refactor: remove unused imports 2026-05-04 21:51:18 +02:00
shayaa 782b0b6bc9 Merge pull request #91 from KeksPirates/feat/bzzhr-impl
Add bzzhr implementation and improve file preallocation on Windows
2026-05-04 21:49:51 +02:00
Vxrtrauter 64ca3c76a2 Fix: update buzzheavier link detection logic and improve filename extraction from headers 2026-05-04 19:07:42 +02:00
dependabot[bot] d6302fc43f build(deps): bump pyinstaller from 6.19.0 to 6.20.0
Bumps [pyinstaller](https://github.com/pyinstaller/pyinstaller) from 6.19.0 to 6.20.0.
- [Release notes](https://github.com/pyinstaller/pyinstaller/releases)
- [Changelog](https://github.com/pyinstaller/pyinstaller/blob/develop/doc/CHANGES.rst)
- [Commits](https://github.com/pyinstaller/pyinstaller/compare/v6.19.0...v6.20.0)

---
updated-dependencies:
- dependency-name: pyinstaller
  dependency-version: 6.20.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-04-23 19:37:36 +00:00
18 changed files with 337 additions and 22 deletions
+15
View File
@@ -46,6 +46,21 @@ jobs:
version: "0.9.7" version: "0.9.7"
enable-cache: true enable-cache: true
- name: Install system dependencies (Linux)
if: runner.os == 'Linux'
run: |
sudo apt-get update
sudo apt-get install -y \
libxcb-xinerama0 \
libxkbcommon-x11-0 \
libxcb-cursor0 \
libxcb-keysyms1 \
libxcb-render-util0 \
libxcb-icccm4 \
libxcb-image0 \
libxcb-shape0 \
libxcb-util1
- name: Install Python dependencies - name: Install Python dependencies
run: | run: |
uv pip install -r requirements.txt uv pip install -r requirements.txt
+15
View File
@@ -51,6 +51,21 @@ jobs:
version: "0.9.7" version: "0.9.7"
enable-cache: true enable-cache: true
- name: Install system dependencies (Linux)
if: runner.os == 'Linux'
run: |
sudo apt-get update
sudo apt-get install -y \
libxcb-xinerama0 \
libxkbcommon-x11-0 \
libxcb-cursor0 \
libxcb-keysyms1 \
libxcb-render-util0 \
libxcb-icccm4 \
libxcb-image0 \
libxcb-shape0 \
libxcb-util1
- name: Install Python dependencies - name: Install Python dependencies
run: | run: |
uv pip install -r requirements.txt uv pip install -r requirements.txt
+28 -4
View File
@@ -18,11 +18,15 @@ jobs:
matrix: matrix:
include: include:
- os: ubuntu-22.04 - os: ubuntu-22.04
artifact_name: SoftwareManager-test-${{ github.sha }}-linux artifact_paths: |
dist-final/SoftwareManager-test-${{ github.sha }}-linux*
dist-final/SoftwareManager-x86_64*
- os: windows-latest - os: windows-latest
artifact_name: SoftwareManager-test-${{ github.sha }}-windows artifact_paths: |
dist-final/SoftwareManager-test-${{ github.sha }}-windows*
- os: macos-latest - os: macos-latest
artifact_name: SoftwareManager-test-${{ github.sha }}-macos artifact_paths: |
dist-final/SoftwareManager-test-${{ github.sha }}-macos*
runs-on: ${{ matrix.os }} runs-on: ${{ matrix.os }}
@@ -41,6 +45,21 @@ jobs:
version: "0.9.7" version: "0.9.7"
enable-cache: true enable-cache: true
- name: Install system dependencies (Linux)
if: runner.os == 'Linux'
run: |
sudo apt-get update
sudo apt-get install -y \
libxcb-xinerama0 \
libxkbcommon-x11-0 \
libxcb-cursor0 \
libxcb-keysyms1 \
libxcb-render-util0 \
libxcb-icccm4 \
libxcb-image0 \
libxcb-shape0 \
libxcb-util1
- name: Install Python dependencies - name: Install Python dependencies
run: | run: |
uv pip install -r requirements.txt uv pip install -r requirements.txt
@@ -134,6 +153,11 @@ jobs:
--name ${{ env.APP_NAME }} \ --name ${{ env.APP_NAME }} \
src/main.py src/main.py
- name: Build AppImage (Linux)
if: runner.os == 'Linux'
shell: bash
run: scripts/build_appimage.sh
- name: Build with PyInstaller (macOS) - name: Build with PyInstaller (macOS)
if: runner.os == 'macOS' if: runner.os == 'macOS'
shell: bash shell: bash
@@ -196,5 +220,5 @@ jobs:
uses: actions/upload-artifact@v7 uses: actions/upload-artifact@v7
with: with:
name: ${{ matrix.os }}-build name: ${{ matrix.os }}-build
path: dist-final/${{ matrix.artifact_name }}* path: ${{ matrix.artifact_paths }}
retention-days: 7 retention-days: 7
+4 -1
View File
@@ -218,4 +218,7 @@ __marimo__/
# Local build files # Local build files
build-local.ps1 build-local.ps1
build-local.bat build-local.bat
# UV
uv.lock
+3 -3
View File
@@ -41,11 +41,11 @@ SoftwareManager is a Python-based GUI tool that simplifies searching and downloa
<!-- python-dependencies:start --> <!-- python-dependencies:start -->
```text ```text
requests (2.33.1) requests (2.34.2)
PySide6-Essentials (6.11.0) PySide6-Essentials (6.11.1)
beautifulsoup4 (4.14.3) beautifulsoup4 (4.14.3)
darkdetect (0.7.1) darkdetect (0.7.1)
pyinstaller (6.19.0) pyinstaller (6.20.0)
PyQtDarkTheme-fork (2.3.6) PyQtDarkTheme-fork (2.3.6)
plyer (2.1.0) plyer (2.1.0)
psutil (7.2.2) psutil (7.2.2)
+7
View File
@@ -0,0 +1,7 @@
[Desktop Entry]
Name=SoftwareManager
Type=Application
Exec=python3 -m SoftwareManager
Icon=softwaremanager
Terminal=false
Categories=X-Software;X-Torrents;
+51 -5
View File
@@ -39,9 +39,10 @@
<h1>KeksPirates</h1> <h1>KeksPirates</h1>
</div> </div>
<nav class="tab"> <nav class="tab">
<a class="tablinks" onclick="openTab(event, 'start')" id="defaultOpen">Home</a> <a class="tablinks" onclick="openTab(event, 'start')" id="navHome">Home</a>
<a class="tablinks" onclick="openTab(event, 'api')">API</a> <a class="tablinks" onclick="openTab(event, 'api')" id="navApi">API</a>
<a class="tablinks" onclick="openTab(event, 'docs')">Docs</a> <a class="tablinks" onclick="openTab(event, 'docs')" id="navDocs">Docs</a>
<a class="tablinks" id="navVst" href="https://vstsearch.softwaremanager.xyz">VST Search</a>
<!-- <a class="tablinks" onclick="openTab(event, 'notfound')">404</a> --> <!-- <a class="tablinks" onclick="openTab(event, 'notfound')">404</a> -->
</nav> </nav>
</header> </header>
@@ -187,6 +188,17 @@
</div> </div>
</div> </div>
<div id="vstsearch" class="tabcontent">
<div class="cse-search">
<h3 class="vst-logo"><span style="color: #db65d5">VST Search</span></h3>
<div class="gcse-searchbox"></div>
<div class="gcse-searchresults"></div>
</div>
</div>
<div id="notfound" class="tabcontent"> <div id="notfound" class="tabcontent">
<div class="notfound-frame"> <div class="notfound-frame">
<h1 class="notfound-title">404</h1> <h1 class="notfound-title">404</h1>
@@ -203,6 +215,20 @@
</footer> </footer>
<script> <script>
const MAIN_ORIGIN = 'https://softwaremanager.xyz';
const VST_ORIGIN = 'https://vstsearch.softwaremanager.xyz';
const onVstDomain = window.location.hostname.startsWith('vstsearch.');
let cseLoaded = false;
function loadCSE() {
if (cseLoaded) return;
cseLoaded = true;
var s = document.createElement('script');
s.async = true;
s.src = 'https://cse.google.com/cse.js?cx=e7334cef72a8b42e7';
document.head.appendChild(s);
}
function openTab(evt, tabName, pushToHistory = true) { function openTab(evt, tabName, pushToHistory = true) {
var i, tabcontent, tablinks; var i, tabcontent, tablinks;
@@ -218,6 +244,8 @@
var target = document.getElementById(tabName); var target = document.getElementById(tabName);
target.style.display = "block"; target.style.display = "block";
if (tabName === 'vstsearch') loadCSE();
// restart animation // restart animation
target.classList.remove('tab-animate'); target.classList.remove('tab-animate');
void target.offsetWidth; void target.offsetWidth;
@@ -247,6 +275,10 @@
// Determine the correct tab immediately (before full load) to prevent flash // Determine the correct tab immediately (before full load) to prevent flash
(function() { (function() {
if (onVstDomain) {
document.getElementById('vstsearch').style.display = 'block';
return;
}
let currentPath = window.location.pathname; let currentPath = window.location.pathname;
let tabName = 'start'; let tabName = 'start';
if (currentPath === '/api') tabName = 'api'; if (currentPath === '/api') tabName = 'api';
@@ -257,9 +289,23 @@
})(); })();
window.onload = function() { window.onload = function() {
if (onVstDomain) {
document.getElementById('navHome').href = MAIN_ORIGIN + '/';
document.getElementById('navApi').href = MAIN_ORIGIN + '/api';
document.getElementById('navDocs').href = MAIN_ORIGIN + '/docs';
['navHome', 'navApi', 'navDocs'].forEach(function(id) {
document.getElementById(id).removeAttribute('onclick');
});
openTab(null, 'vstsearch', false);
document.getElementById('navVst').className += " active";
return;
}
let currentPath = window.location.pathname; let currentPath = window.location.pathname;
if (currentPath === '/api') { if (currentPath === '/vstsearch') {
window.location.replace(VST_ORIGIN);
} else if (currentPath === '/api') {
openTab(null, 'api', false); openTab(null, 'api', false);
} else if (currentPath === '/docs') { } else if (currentPath === '/docs') {
openTab(null, 'docs', false); openTab(null, 'docs', false);
+78
View File
@@ -378,6 +378,84 @@ pre.api-response {
font-size: 2rem; font-size: 2rem;
} }
.cse-search {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
min-height: 70vh;
text-align: center;
}
.cse-search .vst-logo {
font-family: var(--main-font);
font-size: 3.5rem;
font-weight: 700;
letter-spacing: -0.02em;
margin-bottom: 1.5rem;
user-select: none;
}
.cse-search .gsc-control-cse,
.cse-search .gsc-results-wrapper-overlay,
.cse-search .gsc-results-wrapper-visible {
background: transparent !important;
border: none !important;
}
.cse-search .gsc-input-box,
.cse-search .gsc-input-box.gsc-input-box-hover,
.cse-search .gsc-input-box.gsc-input-box-focus {
background: #1a1b1d !important;
border-color: #1a1b1d !important;
}
.cse-search .gsc-input,
.cse-search input.gsc-input,
.cse-search .gsib_a input.gsc-input {
background: transparent !important;
color: #fff !important;
}
.cse-search .gsib_a {
background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none'><path fill-rule='evenodd' clip-rule='evenodd' d='M14.76 13.27L20.49 19L19 20.49L13.27 14.76C12.2 15.53 10.91 16 9.5 16C5.91 16 3 13.09 3 9.5C3 5.91 5.91 3 9.5 3C13.09 3 16 5.91 16 9.5C16 10.91 15.53 12.2 14.76 13.27ZM9.5 5C7.01 5 5 7.01 5 9.5C5 11.99 7.01 14 9.5 14C11.99 14 14 11.99 14 9.5C14 7.01 11.99 5 9.5 5Z' fill='%23ffffff'/></svg>") !important;
}
.cse-search .gsc-search-button-v2 {
background: #db65d5 !important;
border-color: #db65d5 !important;
}
.cse-search .gsc-search-button-v2:hover {
background: #c94dc3 !important;
border-color: #c94dc3 !important;
}
.cse-search .gcsc-more-maybe-branding-root,
.gcsc-find-more-on-google {
display: none !important;
}
.gsc-completion-container,
.gssb_c, .gssb_e,
table.gssb_c, table.gssb_e {
background: #1a1b1d !important;
border-color: #333 !important;
color: #fff !important;
}
.gsc-completion-container td,
.gsc-completion-container .gsc-completion-suggestion,
.gssb_a, .gssb_a td, .gssb_i {
background: #1a1b1d !important;
color: #fff !important;
}
.gsc-completion-container .gsc-completion-selected,
.gsc-completion-container tr:hover td,
.gssb_a:hover td, .gssb_e-hover {
background: #2a2b2d !important;
}
@media(max-width: 560px) { @media(max-width: 560px) {
+55
View File
@@ -0,0 +1,55 @@
// Cloudflare Pages middleware.
//
// Both softwaremanager.xyz and vstsearch.softwaremanager.xyz serve the same
// index.html. Crawlers (Discord, Twitter, etc.) read the raw HTML and do NOT
// run JavaScript, so we rewrite the <title> and Open Graph / Twitter meta tags
// server-side when the request is for the VST Search subdomain. This gives the
// subdomain its own link embed without a separate deploy.
const VST = {
title: "VST Search - SoftwareManager",
description: "Search for plugins easily",
url: "https://vstsearch.softwaremanager.xyz/",
};
class AttributeSetter {
constructor(attribute, value) {
this.attribute = attribute;
this.value = value;
}
element(element) {
element.setAttribute(this.attribute, this.value);
}
}
class ContentSetter {
constructor(value) {
this.value = value;
}
element(element) {
element.setInnerContent(this.value);
}
}
export async function onRequest(context) {
const { request, next } = context;
const response = await next();
const onVstDomain = new URL(request.url).hostname.startsWith("vstsearch.");
const contentType = response.headers.get("content-type") || "";
// Leave everything untouched on the main domain and for non-HTML responses.
if (!onVstDomain || !contentType.includes("text/html")) {
return response;
}
return new HTMLRewriter()
.on("title", new ContentSetter(VST.title))
.on("meta[name='description']", new AttributeSetter("content", VST.description))
.on("meta[property='og:title']", new AttributeSetter("content", VST.title))
.on("meta[property='og:description']", new AttributeSetter("content", VST.description))
.on("meta[property='og:url']", new AttributeSetter("content", VST.url))
.on("meta[name='twitter:title']", new AttributeSetter("content", VST.title))
.on("meta[name='twitter:description']", new AttributeSetter("content", VST.description))
.transform(response);
}
+3
View File
@@ -0,0 +1,3 @@
[build-system]
requires = ["setuptools", "wheel"]
build-backend = "setuptools.build_meta"
+3 -3
View File
@@ -1,8 +1,8 @@
requests==2.33.1 requests==2.34.2
PySide6-Essentials==6.11.0 PySide6-Essentials==6.11.1
beautifulsoup4==4.14.3 beautifulsoup4==4.14.3
darkdetect==0.7.1 darkdetect==0.7.1
pyinstaller==6.19.0 pyinstaller==6.20.0
PyQtDarkTheme-fork==2.3.6 PyQtDarkTheme-fork==2.3.6
plyer==2.1.0 plyer==2.1.0
psutil==7.2.2 psutil==7.2.2
+52
View File
@@ -0,0 +1,52 @@
#!/usr/bin/env bash
echo "Installing Dependencies"
mkdir build
cd build
curl -L -o appimagetool-x86_64.AppImage https://github.com/AppImage/appimagetool/releases/download/continuous/appimagetool-x86_64.AppImage
chmod +x appimagetool-x86_64.AppImage
curl -L -o python.AppImage https://github.com/niess/python-appimage/releases/download/python3.13/python3.13.9-cp313-cp313-manylinux2014_x86_64.AppImage
chmod +x python.AppImage
./python.AppImage --appimage-extract
mv squashfs-root SoftwareManager.AppDir
echo "Build SoftwareManager.whl"
cd ..
build/SoftwareManager.AppDir/AppRun -m build
echo "Prepare SoftwareManager AppImage"
cd build/SoftwareManager.AppDir
./AppRun -m pip install -r ../../requirements.txt
./AppRun -m pip install ../../dist/main-0.0.0-py3-none-any.whl
rm AppRun .DirIcon python.png python*.desktop usr/share/applications/python*.desktop
cp -t ./softwaremanager.png ../../src/interface/assets/logo.png
cp -t . ../../SoftwareManager.desktop
cp ../../SoftwareManager.desktop usr/share/applications/
echo '#! /bin/bash
HERE="$(dirname "$(readlink -f "${0}")")"
export PATH=$HERE/usr/bin:$PATH;
export APPIMAGE_COMMAND=$(command -v -- "$ARGV0")
"$HERE/opt/python3.13/bin/python3.13" "-m" "main" "$@"' > AppRun
chmod -R 0755 ../SoftwareManager.AppDir
chmod +x AppRun
cp /usr/lib/x86_64-linux-gnu/libxcb-cursor.so* ../SoftwareManager.AppDir/usr/lib/
cp /usr/lib/x86_64-linux-gnu/libxcb-xinerama.so* ../SoftwareManager.AppDir/usr/lib/
cp /usr/lib/x86_64-linux-gnu/libxcb.so* ../SoftwareManager.AppDir/usr/lib/
cp /usr/lib/x86_64-linux-gnu/libgssapi_krb5.so* ../SoftwareManager.AppDir/usr/lib
echo " => Build SoftwareManager AppImage"
cd ..
./appimagetool-x86_64.AppImage --appimage-extract
squashfs-root/AppRun SoftwareManager.AppDir
cd ..
echo " => Done "
+1 -1
View File
@@ -113,7 +113,7 @@ class SteamripScraper:
try: try:
consoleLog(f"Found download link: {best}") consoleLog(f"Found download link: {best}")
if "buzzheavier" in best: if "buzzheavier" or "bzzhr" in best:
link = scrape_buzzheavier(best) link = scrape_buzzheavier(best)
return link return link
elif "gofile" in best: elif "gofile" in best:
-1
View File
@@ -12,7 +12,6 @@ import threading
import webbrowser import webbrowser
import subprocess import subprocess
import platform import platform
import time
import os import os
+3 -1
View File
@@ -20,12 +20,14 @@ def add_direct_download(url: str, title: str, dl_path: Optional[str] = None, hea
consoleLog(f"Download already active: {title}") consoleLog(f"Download already active: {title}")
return return
filename = ( raw_filename = (
detect_filename_from_headers(url, DirectDownloadHandle.USER_AGENT) detect_filename_from_headers(url, DirectDownloadHandle.USER_AGENT)
or extract_filename_from_url(url) or extract_filename_from_url(url)
or sanitize_filename(title) + ".zip" or sanitize_filename(title) + ".zip"
) )
filename = sanitize_filename(raw_filename)
handle = DirectDownloadHandle(url, filename, dl_path, headers, single_threaded) handle = DirectDownloadHandle(url, filename, dl_path, headers, single_threaded)
with state.downloads_lock: with state.downloads_lock:
state.active_downloads[url] = handle state.active_downloads[url] = handle
+18 -1
View File
@@ -10,6 +10,7 @@ import requests
import hashlib import hashlib
import json import json
import time import time
import sys
import os import os
@@ -231,8 +232,24 @@ class DirectDownloadHandle:
def _preallocate_file(self, total_size: int): def _preallocate_file(self, total_size: int):
if os.path.exists(self._file_path) and os.path.getsize(self._file_path) == total_size: if os.path.exists(self._file_path) and os.path.getsize(self._file_path) == total_size:
return return
with open(self._file_path, "wb") as f: with open(self._file_path, "wb") as f:
f.truncate(total_size) if sys.platform == "win32":
import msvcrt
import ctypes
from ctypes.wintypes import DWORD
handle = msvcrt.get_osfhandle(f.fileno())
kernel32 = ctypes.windll.kernel32
bytes_returned = DWORD()
kernel32.DeviceIoControl(
handle, 590020, None, 0, None, 0, ctypes.byref(bytes_returned), None
)
kernel32.SetFilePointerEx(handle, ctypes.c_int64(total_size), None, 0)
kernel32.SetEndOfFile(handle)
else:
f.truncate(total_size)
def _compute_chunks(self, total_size: int) -> list[ChunkSpec]: def _compute_chunks(self, total_size: int) -> list[ChunkSpec]:
num_chunks = min(self.NUM_THREADS, max(1, total_size // self.MIN_CHUNK_SIZE)) num_chunks = min(self.NUM_THREADS, max(1, total_size // self.MIN_CHUNK_SIZE))
+1 -1
View File
@@ -34,7 +34,7 @@ def detect_filename_from_headers(url: str, user_agent: str) -> Optional[str]:
if "filename=" in cd: if "filename=" in cd:
parts = cd.split("filename=") parts = cd.split("filename=")
if len(parts) > 1: if len(parts) > 1:
fname = parts[-1].strip().strip('"').strip("'") fname = parts[1].split(";")[0].strip().strip('"').strip("'")
if fname: if fname:
return fname return fname
except Exception as e: except Exception as e:
-1
View File
@@ -4,7 +4,6 @@ from PySide6.QtCore import QObject, QTimer
from utils.data.state import state from utils.data.state import state
from plyer import notification from plyer import notification
import libtorrent as lt import libtorrent as lt
import time
import os import os