Skip to content

Architecture

                    +------------------------------------------+
  browser --------> |  api      REST + WebSocket + embedded UI  |
  CnL button -----> |  cnl      127.0.0.1:9666                  |
  dropped file ---> |  watch    link lists, .torrent, .nzb      |
                    +--------------------+---------------------+
                                         |
                              +----------v----------+
                              |  app                |  tasks, scheduler,
                              |                     |  packages, retries
                              +----------+----------+
                                         |
              +--------------+-----------+-----------+--------------+
              |              |           |           |              |
        +-----v-----+  +-----v-----+ +---v----+ +----v-----+  +-----v-----+
        | crawler   |  | resolver  | | engine | | extract  |  | checksum  |
        | page ->   |  | direct    | | Gopeed | | zip rar  |  | sfv md5   |
        | files     |  | debrid    | | + rate | | 7z tar   |  | sha crc   |
        |           |  | torrent   | |  limit | | gz xz    |  |           |
        |           |  | yt-dlp    | |  proxy | | bz2 zst  |  |           |
        |           |  | headless  | |        | |          |  |           |
        |           |  | JD        | |        | |          |  |           |
        +-----------+  +-----------+ +--------+ +----------+  +-----------+

Every link goes to a resolver, which decides how it is fetched: a debrid service such as TorBox, a hoster account, the torrent client, yt-dlp, your own FTP, SFTP or WebDAV server, the direct path, or the headless JDownloader as the catch-all. When more than one service can take the same link, the order on the Accounts page decides; that includes a magnet link, which a debrid service that takes torrents can fetch in place of the torrent client. JDownloader, yt-dlp and the direct download always come last, because which of them fits depends on the link.

The rate limit lives in a loopback proxy because the embedded engine offers no hook for one. Everything else is a plain Go package with its own tests.

Built on Gopeed (download engine), yt-dlp (media), JDownloader (hoster catch-all, via its local API), Wails (desktop) and React with Tailwind.