[PR #132] [MERGED] [downloader] Keep file extensions and stop producing .bin files #136

Closed
opened 2026-10-13 19:47:48 +00:00 by bsakaguchi · 0 comments
Owner

📋 Pull Request Information

Original PR: https://github.com/Glitchy-Sheep/boosty-downloader/pull/132
Author: @Glitchy-Sheep
Created: 8/9/2026
Status: ✅ Merged
Merged: 8/9/2026
Merged by: @Glitchy-Sheep

Base: main ← Head: fix/no-bin-extensions


📝 Commits (2)

  • ef15050 fix: 🐛 Downloads keep their extensions and never get .bin
  • 534508a refactor: ♻️ Extension policy follows the name's origin, not letter counting

📊 Changes

4 files changed (+120 additions, -5 deletions)

View changed files

📝 CHANGELOG.md (+1 -0)
📝 boosty_downloader/src/application/use_cases/download_single_post.py (+5 -1)
📝 boosty_downloader/src/infrastructure/file_downloader.py (+19 -4)
➕ test/unit/file_downloader/extension_guessing_test.py (+95 -0)

📄 Description

Summary

The downloader used to trust the server's content type over the filename and renamed archive.zip into archive.bin. Research showed there is no universal way to tell whether a name "has an extension" - so the code stops asking. Every download site declares where its name came from, and that origin decides everything.

Fixes #75

Problem

  • The CDN serves file attachments as application/octet-stream ("bytes, type unknown"); mimetypes turns that into .bin and the old code replaced the author's real extension with it
  • Any letter-counting heuristic breaks both ways: .appimage is a real extension longer than the window, and a video titled Update v1.2 looks like it ends with one
  • Live probes of the raw API and all CDN response headers proved the split: files and audio come with the author's original filename, videos and images have no name anywhere - Content-Type is the only source in existence

Fix

The extension policy follows the name's origin, with zero name heuristics:

  • Names from the author (files, audio): never touched, whatever the server says - .doc, .appimage, anything works
  • Names built by the app (videos, images): an informative content type always appends an extension; octet-stream appends nothing, so .bin is never born
  • Extensions are appended to the whole name, not swapped in - dots inside titles cannot truncate it
  • Images finally get .png/.jpg instead of a bare uuid

Before / After

Before: file-sample_1MB.doc lands as file-sample_1MB.bin; images land as extensionless uuids.
After: the file keeps its name; the image becomes 40f9e868-….png; the video becomes Some title (a2dd6942).mp4.

Tests

  • Unit: the octet-stream guard, the content-type source, and two policy guards - flipping download_files back to guessing revives .bin and fails the suite
  • Live, all four chunk kinds through the real app: file (.doc intact, content verified), audio (.mp3 intact), video (.mp4 appended), image (.png appended)
  • Idempotency: a re-run hits the cache, names stay stable; the generated post.html references the new names correctly
  • A full channel download passes end to end; full task ci green

Notes

  • The magic-bytes utility proposed in #75 stays on the roadmap for historic downloads; the probes also mapped richer sources for it (Content-Disposition on files, the fileType field on audio)

🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.

## 📋 Pull Request Information **Original PR:** https://github.com/Glitchy-Sheep/boosty-downloader/pull/132 **Author:** [@Glitchy-Sheep](https://github.com/Glitchy-Sheep) **Created:** 8/9/2026 **Status:** ✅ Merged **Merged:** 8/9/2026 **Merged by:** [@Glitchy-Sheep](https://github.com/Glitchy-Sheep) **Base:** `main` ← **Head:** `fix/no-bin-extensions` --- ### 📝 Commits (2) - [`ef15050`](https://github.com/Glitchy-Sheep/boosty-downloader/commit/ef15050a5a70c3960d4f683111461862730d04d0) fix: :bug: Downloads keep their extensions and never get .bin - [`534508a`](https://github.com/Glitchy-Sheep/boosty-downloader/commit/534508a7b5ba9a9438a1a0e534907243c36c71c1) refactor: :recycle: Extension policy follows the name's origin, not letter counting ### 📊 Changes **4 files changed** (+120 additions, -5 deletions) <details> <summary>View changed files</summary> 📝 `CHANGELOG.md` (+1 -0) 📝 `boosty_downloader/src/application/use_cases/download_single_post.py` (+5 -1) 📝 `boosty_downloader/src/infrastructure/file_downloader.py` (+19 -4) ➕ `test/unit/file_downloader/extension_guessing_test.py` (+95 -0) </details> ### 📄 Description ## Summary The downloader used to trust the server's content type over the filename and renamed `archive.zip` into `archive.bin`. Research showed there is no universal way to tell whether a name "has an extension" - so the code stops asking. Every download site declares where its name came from, and that origin decides everything. Fixes #75 ## Problem - The CDN serves file attachments as `application/octet-stream` ("bytes, type unknown"); `mimetypes` turns that into `.bin` and the old code replaced the author's real extension with it - Any letter-counting heuristic breaks both ways: `.appimage` is a real extension longer than the window, and a video titled `Update v1.2` looks like it ends with one - Live probes of the raw API and all CDN response headers proved the split: files and audio come with the author's original filename, videos and images have no name anywhere - `Content-Type` is the only source in existence ## Fix The extension policy follows the name's origin, with zero name heuristics: - Names from the author (files, audio): never touched, whatever the server says - `.doc`, `.appimage`, anything works - Names built by the app (videos, images): an informative content type always appends an extension; `octet-stream` appends nothing, so `.bin` is never born - Extensions are appended to the whole name, not swapped in - dots inside titles cannot truncate it - Images finally get `.png`/`.jpg` instead of a bare uuid ## Before / After **Before:** `file-sample_1MB.doc` lands as `file-sample_1MB.bin`; images land as extensionless uuids. **After:** the file keeps its name; the image becomes `40f9e868-….png`; the video becomes `Some title (a2dd6942).mp4`. ## Tests - Unit: the octet-stream guard, the content-type source, and two policy guards - flipping `download_files` back to guessing revives `.bin` and fails the suite - Live, all four chunk kinds through the real app: file (`.doc` intact, content verified), audio (`.mp3` intact), video (`.mp4` appended), image (`.png` appended) - Idempotency: a re-run hits the cache, names stay stable; the generated `post.html` references the new names correctly - A full channel download passes end to end; full `task ci` green ## Notes - The magic-bytes utility proposed in #75 stays on the roadmap for historic downloads; the probes also mapped richer sources for it (`Content-Disposition` on files, the `fileType` field on audio) --- <sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
bsakaguchi 2026-10-13 19:47:48 +00:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
Glitchy-Sheep/boosty-downloader#136
No description provided.