How GolinksPRO Download Manager's pieces fit together.
Крейты
| Путь | Крейт | Роль |
|---|---|---|
crates/engine |
mdm-engine |
Загружает один файл по HTTP(S) или FTP(S): зондирование, планировщик сегментов, рабочие соединения, состояние возобновления, ограничения на хост, ограничитель скорости, контрольные суммы, прокси-скрипты |
crates/app |
mdm-app |
Настольное приложение (misterdownloadmanager.exe, egui): список, категории, очереди, планировщик, диалоги, трей, настройки |
crates/cli |
mdm-cli |
Загрузки без графического интерфейса с индикатором выполнения (get, resume), видео, торренты и команды API автоматизации: библиотека, которую запускает программа приложения (misterdownloadmanager --cli …), и misterdownloadmanager-cli — небольшой лаунчер, который запускает её с теми же аргументами, терминалом и кодом выхода. |
crates/mcp |
mdm-mcp |
Сервер MCP (misterdownloadmanager-mcp): список ИИ-помощников, добавление и управление загрузками запущенного приложения через API автоматизации |
crates/remote |
mdm-remote |
Удаленное управление (#141): HTTPS-сервер, который использует сопряженный телефон или компьютер в локальной сети (его страница, коды сопряжения, токены устройств, самоподписанный сертификат); каждый запрос становится командой API автоматизации, на которую отвечает приложение |
crates/nmhost |
mdm-nmhost |
Хост нативных сообщений браузера: принимает перехваченные загрузки от расширения и передает их приложению |
crates/ipc |
mdm-ipc |
Канал единственного экземпляра (локальный сокет, защищенный токеном), папка данных и правила перехвата, общие для приложения и хоста |
crates/debrid |
mdm-debrid |
Учетные записи дебрид-сервисов (#44): официальные API-интерфейсы сервисов (Real-Debrid, AllDebrid, Premiumize) преобразуют ссылку файлового хостинга в прямую ссылку, которую загружает движок. |
crates/extract |
mdm-extract |
Распаковка архивов (#37): zip, tar, gz и xz в процессе; 7z и RAR через установленный 7-Zip, запускаемый как отдельная программа. |
crates/geo |
mdm-geo |
Местоположение сервера загрузки (#140): таблица диапазонов IP-адресов по странам, построенная на основе данных DB-IP Lite (tools/geo/build.py), поиск выполняется только на этом компьютере, а также флаги стран. |
crates/tools |
mdm-tools |
Video pages through yt-dlp and ffmpeg, image galleries through gallery-dl (run as separate programs); while a network adapter is chosen, their connections go through a proxy of GDM's on 127.0.0.1 that binds them to it (relay.rs) |
crates/crash |
mdm-crash |
Отчеты о сбоях и зависаниях: процесс монитора, минидампы вне процесса, символизированные стеки, текст отчета и журналы выпуска (crash-reports.md) |
crates/torrent |
mdm-torrent |
BitTorrent и magnet-ссылки через librqbit |
crates/labserver |
mdm-labserver |
HTTP Range-сервер с журналом запросов и внедрением ошибок, а также FTP/FTPS-сервер со своими ошибками, для тестов и бенчмарков |
extension/ |
— | Расширение для Chromium (MV3) и Firefox |
docs/ |
— | Руководство пользователя и учебные пособиям, этот файл, данные для бенчмарка; веб-сайт делает руководство своими страницами справки, которые открывает Справка |
website/ |
— | Собственные страницы misterdownloadmanager.com (главная, загрузка, возможности, темы, FAQ); tools/website/build.py добавляет справку из docs/ и новости из CHANGELOG на 22 языках, а GitHub Pages публикует их. |
Зависимости направлены внутрь: app, cli, mcp, nmhost и remote используют engine и ipc; движок ничего не знает о пользовательском интерфейсе. Приложение видит движок только через его события (прогресс, снимки таблицы сегментов, завершено, сбой).
Движок
Download
├─ probe() size, resumable?, validators (ETag / Last-Modified), file name
├─ Planner (pure) segment table: when a connection is free, the largest remaining
│ part is split in half (planner.rs, tested by random simulation)
├─ Worker × N one HTTP/1.1 connection each, reused across segments; slow ones
│ are dropped and their part re-split
│ └─ writes at its offset into <name>.mdm.part (created sparse)
├─ HostLimits learns how many connections each server accepts
├─ Limiter (shared) per-download and global token buckets
├─ State segment table saved atomically (craft-atomic) for crash-safe resume
└─ events → channel Progress, Done, Failed
Когда все сегменты загружены, файл .part проверяется на соответствие ожидаемому размеру и переименовывается; дата файла может соответствовать дате сервера.
Первый запрос на скачивание (get) следует перенаправлениям и страницам, которые сами ведут к файлу (обновление страницы ожидания). Для сайтов, чьи ссылки не являются адресом файла, в sites/ есть модуль (Google Drive: sites/gdrive.rs): он преобразует ссылку в адрес файла, читает собственные страницы сайта (форма подтверждения, страница ошибки) и называет его отказы (Error::Refused), используя чистые функции, протестированные без сети. Лабораторный сервер имитирует такой сайт на его реальных хост-именах для сквозных тестов (labserver/src/drive.rs).
FTP и FTPS (ftp.rs) проходят через тот же планировщик, рабочие процессы и состояние: сегмент — это REST + RETR в управляющей сессии вместо диапазонного GET, SIZE и MDTM заменяют заголовки, а сессии объединяются для каждой загрузки и повторно используются между сегментами.
Приложение
Одно окно egui отрисовывается в фиксированных пиксельных координатах, плюс один непосредственный видовой экран на каждое диалоговое окно. app.rs хранит состояние (загрузки, очереди, параметры, выбор в списке) и преобразует команды меню, панели инструментов, клавиш и IPC в действия. Каждое диалоговое окно является отдельным модулем и возвращает Outcome (открыто, закрыто, выполнено со значением). Вызовы, специфичные для Windows, ограничены win32.rs, а их аналоги для Linux и macOS — unix.rs (запуск с сессией, хост браузеров, звуки, показать в папке, обработчик сбоев); все остальные файлы — безопасный, переносимый Rust. Шрифты берутся из системы: папка Fonts в Windows, системные шрифты macOS, fontconfig в Linux (theme.rs). В Windows текст на латинице, греческом и кириллице отрисовывается DirectWrite в режиме GDI-classic (win32.rs, через хук растрирования глифов egui), так что подсказанная форма каждой буквы и ширина в целых пикселях объединяются; другие скрипты формируются и отрисовываются egui.
Темы
Каждый цвет и размер элемента управления определяется активной темой (#45). Тема состоит из светлой и темной палитры, метрик, стилей элементов управления и стиля значков (palette.rs):
- Роли палитры.
palette.rsобъявляет каждую роль со стабильным ключом ("button.hot","list.row","caption"…), описанием и значениями для светлой и темной тем классического вида, записанными явно (классический вид не является производным). Общие отрисовщики (winui.rs,chrome.rs,list.rs,scrollbar.rs) считывают их черезtheme::colors()иtheme::metrics()и определяют состояния каждого элемента управления на их основе; ни один код отрисовки не содержит собственного цвета. - Производные палитры.
derive.rsсоздает целую палитру из нескольких исходных цветов (фон, поверхность, текст, акцент…), смешивая все остальные роли в OKLab и сохраняя контраст WCAG (4.5:1 для текста, 3:1 для краев); «Высокая контрастность» усиливает каждый край сверху.native.rsинициализирует системную тему из системного акцента и контраста (настройки Windows, портал freedesktop в Linux, акцент macOS). - Control styles.
palette::Controlsnames each control's shape (text boxes, check boxes, buttons, progress bars, scroll bars, the focus mark, the title bar); the style themes (Metro, Adwaita, Breeze, Luna, Aero, Aqua) pick theirs, and on Windows GDM then draws the title bar itself (thecaption.*roles). - Файлы тем.
themefile.rsсчитывает TOML или JSON из папки данныхthemes(один файл или<id>/theme.tomlсо значками рядом). Файл называет только то, что он изменяет; остальное берется из темы, которую онinherits(идентификатор встроенной темы или другого файла, по умолчанию — классический вид), по цепочке, в которой цикл не допускается. Неизвестные ключи являются предупреждениями, а не ошибками. Встроенные стили тем также являются такими файлами, содержащимися в программе (crates/app/assets/themes). - Наборы значков.
themeicons.rsотрисовывает значки темы (названные по их назначению:tb-add-url,cat-music…, SVG или PNG размером 16, 24, 32 и 48 пикселей,-symbolicзначки, окрашенные в цвет текста) там, где классический вид отрисовывает свои собственные; если в наборе отсутствует необходимый значок, используется классический.
Расположение элементов управления в окне остается его макетом. То же самое относится к значкам перед именами файлов (fileicons.rs): системные списки изображений оболочки Windows, macOS Finder (NSWorkspace), тема значков рабочего стола Linux (xdgicons.rs, shared-mime-info и Icon Theme Specification). Каждый тип ищется один раз для каждого размера пикселя в фоновом потоке. Значки Tango (в комплекте) используются до тех пор, пока системный значок не будет готов, и везде, где система его не имеет.
Отрисовка
The windows are drawn with OpenGL (eframe's glow) or with the system's own graphics API through
eframe's wgpu, with that one backend only: Direct3D 12 on Windows (the default there), Vulkan on
Linux, Metal on macOS (choices there; OpenGL stays their default until real graphics cards have
tried them, #206). View → Draw with picks one, from the next start. One code path does it on
every system (crates/app/src/renderer.rs): when the chosen one can't start, the other one is
tried, so the windows always open. A watched start with the system's API leaves a marker until
its first frame is drawn: a start that ends before it (a crash inside the driver), one whose
first frame doesn't come within 10 seconds (GDM then starts again with OpenGL), or a graphics
card lost twice in 10 minutes is remembered with its reason, which the menu shows.
View → Interface size (scale.rs, #262) is egui's zoom factor over the display's own scale:
every window is laid out in points, so it opens that much larger; one larger than the screen
scrolls.
Данные
The download list and settings are saved atomically to the data folder (downloads.json):
%APPDATA%\misterdownloadmanager\ on Windows, ~/.local/share/misterdownloadmanager on Linux,
~/Library/Application Support/misterdownloadmanager on macOS, a data folder beside a portable
copy, or MDM_DATA_DIR (mdm_ipc::data_dir). The browser host reads the same file for the
capture rules, so a change in Options applies to the next captured download.
Sign-in secrets (debrid accounts, Sites Logins' and the proxy's passwords) live in the system's
keychain (secrets.rs, #44): Windows Credential Manager (win32.rs), the Secret Service on Linux
or the macOS keychain (unix.rs). The settings keep a keychain:<service>/<scope>/<key>
reference in their place, written only once the keychain has confirmed the secret; without a
keychain (or with a locked one, never unlocked for GDM) the secret stays in the settings as
before.
Местоположение сервера загрузки (#140) — это страна адреса, к которому он подключился, ищется в таблице mdm-geo на этом компьютере (countries.rs называет ее на языке интерфейса); задание выпуска перестраивает таблицу из данных месяца (tools/geo/build.py --release).
Интеграция с браузером
page ──► extension ──native messaging──► mdm-nmhost ──ipc──► app
Расширение запрашивает у хоста, какие типы файлов принимать, проверяет каждую загрузку на соответствие им и отменяет загрузку браузера только после того, как приложение ее приняло; в противном случае браузер сохраняет ее, и расширение объясняет причину.
The host serves only GDM's own extension. Its IDs are in one place, mdm_ipc::extension
(crates/ipc/src/extension.rs): the unpacked copy's (UNPACKED_ID, from the manifest's public
key), the Chrome Web Store's (STORE_ID, signed with the store's own key: pack.ps1 leaves the
manifest's key out of the store's copy), the Firefox add-on's (FIREFOX_ID) and its
addons.mozilla.org page; the Edge and Opera stores' are placeholders, never served, until the
extension is listed there. The host writes each browser's manifest with those IDs, and the app
offers the store's copy (Add to Chrome, Add to Firefox) before the unpacked one.
Удаленное управление
phone ──HTTPS (paired token)──► mdm-remote ──ipc::Sink──► app (answer, remote_add)
--headless(headless.rs, #157) запускает тот же App без eframe: цикл вызывает его tick (то, что logic запускает в каждом кадре) на чистом egui::Context, пробуждаемом каналом команд, и никогда его ui; команды добавляются по мере их добавления пультом дистанционного управления (без окна). Dockerfile и docker/ (Compose, шаблон Unraid) запускают его на сервере (server.md).
Сервер работает на Tokio-среде выполнения приложения, по одному слушателю на каждый адрес локальной сети. Каждый запрос проверяется (Host, Origin, токен), преобразуется в mdm_ipc::Command, помеченный remote (поле, которое не может быть установлено строкой запроса), и передается приложению через тот же канал, что и командная строка; приложение отвечает на него в следующем кадре, как оно отвечает на API автоматизации. Его страница встроена (crates/remote/web), а тексты берутся из каталогов приложения (remote.rs).
Переводы
Каждый текст, отображаемый в пользовательском интерфейсе, проходит через crate::i18n (каталоги craft-i18n, i18n/<locale>.tsv). tools/i18n/extract.py перестраивает i18n/en.tsv из исходного кода, с примечанием для переводчиков к каждому тексту (что это, где отображается, его заполнители). tools/i18n/translate.py заполняет то, чего не хватает в других каталогах (строки, помеченные #, machine), следуя руководству по стилю каждого языка (i18n/style/) и глоссарию; строка, проверенная человеком, никогда не заменяется, а CI (reviewed_guard.py) отклоняет изменение, которое удаляет ее. Веб-сайт имеет свои собственные каталоги (i18n/site/, tools/website/translate_site.py).
Изображения
The help pages' pictures (docs/images/help/) come from one list, tools/shots/shots.toml:
tools/shots/make.py opens each window through GDM's own /show <window> command line in a test
instance off the screen, crops and annotates it from the window's accessibility tree, and writes
lossless WebP; make.py check (CI) keeps the list, the pages and the files in step. The
published ones are taken on GitHub's Windows runner (docs-shots.yml).
Участники
tools/contributors.pyчитает, кто открывал запросы на слияние и проблемы, и кто комментировал, из публичного API GitHub (без учета сопровождающего, Клода и ботов) для каждого места, где им выражается благодарность: домашняя страница веб-сайта, /contributors.html и каждый выпуск на странице «Новости» (build.py, в каждой сборке), примечания к каждому выпуску (release.yml, люди, активные с предыдущего выпуска) и README (python tools/contributors.py readme при подготовке каждого выпуска: его круглые фотографии фиксируются в art/contributors/, так как GitHub не может округлить изображение в README).
Тесты и бенчмарки
cargo testзапускает модульные тесты и сквозные загрузки против mdm-labserver с внедренными ошибками (медленные, отброшенные и отклоненные соединения, серверы без диапазонов, изменяющиеся файлы). tools/bench запускает опубликованное сравнение скоростей; его необработанные данные находятся в docs/bench/.
Бесплатно, с открытым исходным кодом, без рекламы, без пробного периода.
Download GolinksPRO Download Manager