Nothing in the repository says how a release is made, so the details live only in the workflows and in the history.
- `docs/source/release-process.rst`: the two version files that have to move together, cutting a release on its own branch, what `release: published` triggers, why the tag is not an ancestor of `main`, what each tag in the repository means, and where the artifacts land.
- `docs/source/locale/zh_CN/LC_MESSAGES/release-process.po`: the translation, following the existing gettext setup. 39 message ids, checked against the catalogue Sphinx extracts from the page, and rendered with `-D language=zh_CN`.
- `docs/source/index.rst`: one line in the toctree.
The tag section is the part that has cost time: `nightly-*` move on every push, and the legacy `main` and `dev` tags shadow the branches of the same name, so `git show main:path` answers from the tag.
`pyinstaller.yml` only runs on pushes to `main` and `dev`, so `maigret_standalone.exe` exists only on the moving `nightly-*` tags. Every stable release from v0.6.1 to v0.6.5 has zero assets, and winget and Scoop cannot pin a moving tag by hash.
- add the `release: types: [published]` trigger, the same one `python-publish.yml` uses. Checkout resolves `refs/tags/<tag>`, so the exe is built from the released code.
- guard the two nightly-only steps on `github.event_name == 'push'`, otherwise `NIGHTLY_TAG` becomes `nightly-v0.6.5` and creates a junk tag beside the real one.
- add a step attaching the binary to the published release with every `omit*DuringUpdate` set, so the title, body, prerelease and draft state are left alone.
- `tests/test_workflows.py`: the `release_step` fixture asserted there was exactly one `release-action` step, which a second one breaks. It now selects a step by the event it is guarded on, and the new step gets its own guards: every release step must be event specific, the published one must set all four omits, and it must target `github.event.release.tag_name` rather than `NIGHTLY_TAG`.
Existing releases are not backfilled. A release now costs two PyInstaller runs, one on the tag and one on the push to `main` that follows.
`os.makedirs(report_dir)` runs unguarded, so a working directory without write permission ends the run with a raw traceback through asyncio and exit 1:
PermissionError: [Errno 13] Permission denied: '/var/lib/snapd/void/reports'
- `maigret/maigret.py`: catch `OSError`, name the directory and the fix, exit 2 to match the other setup failures.
- under snap, add a line explaining where that path came from: outside `$HOME` and connected removable media snapd substitutes `/var/lib/snapd/void` for the working directory, so the error names a path the user never typed.
Not snap specific, the same traceback appears on any install run from a read-only or root-owned directory.
New "Isolated installation with pipx" section in `installation.rst`, between the PyPI and GitHub ones: `pipx install maigret`, the `pdf` extra, upgrade, uninstall, and a note for uv users.
Until now pipx appeared only in the FAQ, as a fix for `maigret: command not found`.
`utils/` is in neither the sdist nor the wheel, so the declared entry point ships a command that fails on every install:
$ update_sitesmd
ModuleNotFoundError: No module named 'utils'
It only works in a dev checkout, where maigret is installed editable and the repository root is on sys.path.
- `pyproject.toml`: drop the `update_sitesmd` script.
- `.githooks/pre-commit`: run `python -m utils.update_site_data` instead.
- `installation.rst`: the quoted pip warning named both scripts, now one.
The snap has been on `latest/stable` since 26.08, for amd64 and arm64, and is mentioned nowhere a user would look. The only match in the repository is `settings.rst`, in passing, as an example of an install whose directory is not writable.
- `README.md`: a "Snap (Linux)" subsection before the pip one, with the official Snap Store badge at the same height as the Cloud Shell buttons above it.
- `docs/source/installation.rst`: the same, between Cloud Shells and PyPI, with the badge under `only:: html` like the other buttons on that page, plus what strict confinement means in practice, the `removable-media` interface, and automatic updates through snapd.
Every one of them is a site that answers the same way for any username, so the check said "claimed" for everyone.
Two of them are proof-of-work interstitials that come back with a 2xx, and those are worth a global marker rather than a per-site patch: joyreactor.cc now runs Anubis (`/.within.website/x/`, HTTP 200 on every path) and fixya.com serves an HTTP 202 with `window.POW_CHALLENGE_DATA`. Both are vendor products used far beyond these two sites, so they go into COMMON_ERRORS and the sites report bot protection instead of a hit.
The rest are per-site rot. championat.com answers every `/user/*` with the same 686-byte SberID auth stub, profiles are behind login now, disabled. forum.heroesworld.ru redirects to the forum index, which never contains the vBulletin absence marker, the forum has moved to `heroesworld.ru/user/{username}/` where a missing user is a clean 404. Codédex was a status_code check and flapped to 200 on a missing profile once in about fifteen requests, so it now matches the og:title of a real profile.
OP.GG search falls back to other regions when the requested one has no hit: `?q=soxoj®ion=ru` returns an Oceania summoner, and the shared engine marker `href="/lol/summoners/` matched it, so all seventeen region entries claimed the account. The marker moves from the engine to each site with its region baked in. Name matching is already exact on op.gg's side, `q=blaz` returns only summoners named exactly Blaz, so the region was the whole leak.
A XenForo board can let a member hide their profile from guests. The
profile then answers 403 with a login page, and the engine already handles that
- `You must be logged-in to do that.` and its Russian, French and Turkish
translations are presence strings, not absence ones.
The list has no Hebrew or Persian. On `tapuz.co.il` two of the seven members its
own directory offers are login-walled, and on `forumroman.com` one of four; all
of them are reported as available today.
Both strings were checked against the absence page of four XenForo boards -
prog.co.il, tapuz.co.il, iranjoman.com, forumroman.com - and appear on none of
them.
Completes subtask 2 of #2668. When manual feature detection sees a claimed profile return 2xx and the unclaimed profile return 4xx, --submit creates a status_code check. Redirects keep the message fallback.
The instance is gone. DNS still resolves (23.131.76.144) but the host
refuses connections on both 443 and 80.
Checked against three other federated instances added in the same sweeps -
foxes.day, best-friends.chat and mitmachim.top all answer 200 from here -
so this is the site rather than the checking address.
The Snap Store rejects any upload whose summary contains unicode control characters, and the detective emoji in ours is a ZWJ sequence: U+1F575 U+FE0F U+200D U+2642 U+FE0F. The joiner is category Cf, so the upload fails review with `summary: Control/private unicode characters are not allowed` after processing completes.
snapcraft's metadata linter warns that the `website` field is missing, and the store listing page shows a Website link that would otherwise be empty.
Pointing it at the documentation rather than the repository, since `source-code` already carries the GitHub URL. With this the build passes all four linters silently.
* fix: don't treat refused or self-redirected responses as not-found
401 and 429 fell through to the checkType branch, where any non-2xx code means the username is free, so blocked and rate-limited requests were reported as confirmed absences; they now return errors, Vercel's Security Checkpoint joins the bot-protection markers, and a self-redirect that carries Set-Cookie is retried once instead of read as an absence.
* Fix site checks: 16 sites, 3 fixed, 12 disabled, 1 dead deleted
* docs: note that the joyreactor self-redirect is intermittent
save_graph_report handed the file off to pyvis's show(), which opens it with
open(name, "w+"), i.e. the locale encoding. On Windows that is the ANSI
codepage (cp1252 by default), and the vis-network bundle pyvis inlines carries
several hundred non-ASCII characters of its own, so every graph report died
with UnicodeEncodeError regardless of what was scanned. The CLI aborted
mid-run and left a 0-byte html file behind; the web interface builds a graph
for every scan, so each one ended as "Search failed" and discarded the
results.
Render the html and write it here with encoding="utf-8" instead. The debug.log
dump and the report template read had the same implicit encoding, so they get
the same treatment.
Three existing tests (test_build_reports_computes_found_count,
test_real_report_generation_does_not_crash, test_live_scan_streams_found_and_done)
fail on a non-utf-8 machine before this change and pass after it. The new tests
perform the writes under -X warn_default_encoding, so a return to the implicit
encoding fails on CI too, where the locale is utf-8 and the bug is invisible.