GolinksPRO Download Manager
  1. Главная
  2. Справка
  3. Архитектура

Архитектура

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::Controls names 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 (the caption.* 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