Thanks for your interest in contributing!
- Fork the repository
- Create a branch for your feature or fix
- Test your changes against both providers (datanodes.to and fuckingfast.co)
- Run the verification suite (below) — it is fast and catches the regressions that actually happened
- Submit a pull request describing what changed and why
Looking for something to pick up:
- good first issue — scoped small, with the files to touch and the acceptance criteria already written out
- help wanted — everything open to outside contributors, including the larger items
Each issue says up front whether it needs Windows. Several do not — documentation, CI and dependency
work all run anywhere, and the no-Chrome test suite stubs the browser and the network at the
moon_extract boundary so it runs on any OS.
Comment on an issue before you start, so two people don't write the same patch.
Two front-ends, one engine, one extraction layer.
moon_bridge.py loopback HTTP + token, launches Edge/Chrome --app, OS dialogs
web/ index.html · styles.css · app.js the GUI
moon_engine.py the engine with no GUI: start/stop/snapshot
moon_extract.py datanodes (real Chrome over CDP) · fuckingfast (curl_cffi)
BrowserGate: the launch, deferred until a datanodes link
moon_cli.py argparse CLI, same engine, same extraction layer
Layers inside the engine:
- Extraction —
moon_extract.py, shared by all three front-ends - Download engine — aiohttp, Range-header resume, stall detection, proxy rotation
- Telemetry — 1 Hz snapshots,
.txt+.jsonoutput - GUI —
web/over the loopback API, hosted bymoon_bridge.py
- Shared logic goes in
moon_extract.py, not copy-pasted between front-ends. If a change touches extraction or the Chrome lifecycle, it must land in one place and be visible from bothmoon_engine.pyandmoon_cli.py. - Never open a browser before you know you need one. Ask
BrowserGate.get()inside the provider branch that requires it. A launch at the top of a run is the bugtest_no_chrome.pyexists to prevent. moon_engine.pyandmoon_cli.pystill carry their own copy of the download engine (download_file,Telemetry,ProxyPool). A fix to one belongs in both until that code moves into a shared module.- No new dependencies without a strong reason. The stack is deliberately small:
aiohttp,playwright,curl_cffi. - English only. Code, comments, log lines, dialog titles and docs. The GUI's EN/IT
dictionary in
web/app.jsis the one exception — that is the runtime language switch.
python test_no_chrome.py # no browser for fuckingfast, exactly one for datanodes
python integration_http.py # browser -> loopback HTTP -> engine
python integration_web.py # pywebview path
python render_gui.py out/ # GUI renders + overflow audittest_no_chrome.py stubs Chrome and the network at the moon_extract boundary, so it
needs no browser, no display and no Playwright install.
Live testing: at least 10 links per provider, including one guaranteed-dead one so dead-link detection is exercised, and one session long enough (40+ files) to hit the concurrency paths.
Use the bug report template
and attach moontech_*.log (GUI) or moontech_cli_*.log (CLI). MOON_DEBUG=1 adds
extraction-level tracing.
- 4-space indentation, no tabs.
- f-strings over
%or.format(). - Top-level constants uppercase (
RECV_CHUNK,WRITE_BUF,DN_LANES). - No blanket
except:— name the exception, orexcept Exception:with a comment when the swallow is deliberate. - Comments explain why, not what. The gotchas in
moon_extract.pyare the model: each one states a specific fact that cost a debugging session. - Match the surrounding style. Read the nearby code first.