Add Cloudflare bypass (FlareSolverr) support to web UI + docs (#2700)

This commit is contained in:
Soxoj
2026-05-25 18:53:18 +02:00
committed by GitHub
parent fe93347da1
commit 9a2cce4d85
6 changed files with 401 additions and 238 deletions
+4
View File
@@ -292,6 +292,10 @@ Activate the bypass either with the CLI flag::
maigret --cloudflare-bypass <username>
or by setting ``cloudflare_bypass.enabled`` to ``true`` in ``settings.json``.
The web UI (``python -m maigret.web.app``) reads the same setting — there is
no separate toggle in the form, so flipping ``enabled`` is what activates
the bypass for browser-driven runs.
The bypass only fires for sites whose ``protection`` field intersects
``cloudflare_bypass.trigger_protection`` (default
``["cf_js_challenge", "cf_firewall", "webgate"]``); all other sites use the
+103 -95
View File
@@ -6,7 +6,7 @@ msgid ""
msgstr ""
"Project-Id-Version: Maigret 0.6\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2026-05-23 09:20+0200\n"
"POT-Creation-Date: 2026-05-25 18:02+0200\n"
"PO-Revision-Date: 2026-05-22 21:00+0200\n"
"Last-Translator: \n"
"Language: zh_CN\n"
@@ -17,86 +17,85 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n"
"Generated-By: Babel 2.18.0\n"
#: ../../source/features.rst:4 c5c6b9457ad64524a5e85fce2a39162e
#: ../../source/features.rst:4 eca41ada7a9f4545800a2d110503a14a
msgid "Features"
msgstr "特性"
#: ../../source/features.rst:6 db9219d1ce9f4d65ac3e8bbf94388511
#: ../../source/features.rst:6 b24b658bc3bd4954af7bd8307d12dd42
msgid "This is the list of Maigret features."
msgstr "以下是 Maigret 的特性列表。"
#: ../../source/features.rst:11 4e6480fbc44c46a29ba7733626bbb429
#: ../../source/features.rst:11 8d83920098174365a4969a42ba7ceac6
msgid "Web Interface"
msgstr "Web 界面"
#: ../../source/features.rst:13 d8e360bd959d4492879ccbe03cdb12f1
#: ../../source/features.rst:13 5957db1bd94f4d7ab214b92c06d67e73
msgid ""
"You can run Maigret with a web interface, where you can view the graph "
"with results and download reports of all formats on a single page."
msgstr "你可以以 Web 界面的方式运行 Maigret —— 在同一个页面里查看结果图谱、并下载所有格式的报告。"
#: ../../source/features.rst:16 276bbc14f19943adacaa55e2ad826c3c
#: ../../source/features.rst:16 7631566c1cfd402b80ba138921568711
msgid "Web interface: how to start"
msgstr "Web 界面:启动页"
#: ../../source/features.rst:20 e870c6257bce4c6584b0fb369f2e153e
#: ../../source/features.rst:20 deda308a1ecb4354a06c77ae44d74f64
msgid "Web interface: results"
msgstr "Web 界面:结果页"
#: ../../source/features.rst:24 f01248c0e652464fb715af3d02c7526e
#: ../../source/features.rst:24 035b97ee389442efa904d58e7675819d
msgid "Instructions:"
msgstr "使用步骤:"
#: ../../source/features.rst:26 3b4eb508b7f04665902a64c8b72ed143
#: ../../source/features.rst:26 7d8d5e3519cd45f8996e3901d59b4745
msgid "Run Maigret with the ``--web`` flag and specify the port number."
msgstr "使用 ``--web`` 参数运行 Maigret,并指定端口号。"
#: ../../source/features.rst:32 98ddaf990579422ba19473f5c3281d12
#: ../../source/features.rst:32 f99c4e96a1794fdebbca1eb8de276e7e
msgid ""
"Open http://127.0.0.1:5000 in your browser and enter one or more "
"usernames to make a search."
msgstr "在浏览器中打开 http://127.0.0.1:5000,输入一个或多个用户名以发起搜索。"
#: ../../source/features.rst:34 9919b43f50d247a09834623389e7ff21
#: ../../source/features.rst:34 d7e33c3780724f95bf553821485840b8
msgid ""
"Wait a bit for the search to complete and view the graph with results, "
"the table with all accounts found, and download reports of all formats."
msgstr "稍等片刻搜索完成后,即可查看结果图谱、列出全部已发现账号的表格,并下载所有格式的报告。"
#: ../../source/features.rst:39 34b07aff9d134c4386412945cf1fb0dc
#: ../../source/features.rst:39 20f45c4b369b419e883745ee1d31152f
msgid "Telegram bot"
msgstr "Telegram 机器人"
#: ../../source/features.rst:41 ed98e98c542e493eb41515251fa9c79f
#: ../../source/features.rst:41 06eb5827613b479583d051a01176b920
msgid ""
"A community-maintained Telegram bot lets you run Maigret without "
"installing anything locally."
msgstr ""
"社区维护的一个 Telegram 机器人让你无需在本地安装就能运行 Maigret。"
msgstr "社区维护的一个 Telegram 机器人让你无需在本地安装就能运行 Maigret。"
#: ../../source/features.rst:44 5ae5c3250cb442f9bffc21d41afbb5ee
#: ../../source/features.rst:44 7465f025cb9141fbb92af0576662eccc
msgid ""
"Working instance: `sites.google.com/view/maigret-bot-link "
"<https://sites.google.com/view/maigret-bot-link>`_ (redirect — the hosted"
" bot may move between providers)."
msgstr ""
"在线实例:`sites.google.com/view/maigret-bot-link <https://sites.google."
"com/view/maigret-bot-link>`_\\ (跳转链接 —— 托管实例可能会在不同服务商"
"之间迁移)。"
"在线实例:`sites.google.com/view/maigret-bot-link "
"<https://sites.google.com/view/maigret-bot-link>`_\\ (跳转链接 —— "
"托管实例可能会在不同服务商之间迁移)。"
#: ../../source/features.rst:47 1fa5f0bc407a4c359d6041a67d1b3cec
#: ../../source/features.rst:47 eb79c93a7e8b4de4a207568ffdd52b35
msgid ""
"Source code: `github.com/soxoj/maigret-tg-bot <https://github.com/soxoj"
"/maigret-tg-bot>`_."
msgstr ""
"源代码:`github.com/soxoj/maigret-tg-bot <https://github.com/soxoj/"
"maigret-tg-bot>`_。"
"源代码:`github.com/soxoj/maigret-tg-bot <https://github.com/soxoj/maigret-"
"tg-bot>`_。"
#: ../../source/features.rst:51 96f177df09cc44baa106d38c929bdfda
#: ../../source/features.rst:51 f83b69f1fcba4abeb66a12a711d151f1
msgid "Personal info gathering"
msgstr "个人信息收集"
#: ../../source/features.rst:53 0a261aa82b064f3f9ecf8e5bd1ddd850
#: ../../source/features.rst:53 2913acff61f8466e80dc03285b75c54b
msgid ""
"Maigret does the `parsing of accounts webpages and extraction "
"<https://github.com/soxoj/socid-extractor>`_ of personal info, links to "
@@ -108,15 +107,15 @@ msgstr ""
"个人信息、指向其它主页的链接等内容。抽取结果会以附加信息的形式出现在 CLI 输出中,并在 HTML 和 PDF "
"报告中以表格呈现。此外,Maigret 还会用从链接中发现的 ID 和用户名,启动递归搜索。"
#: ../../source/features.rst:57 2cadf584fa4c4b918a60b0f9cbc0cfd8
#: ../../source/features.rst:57 774c604cfa0d48ac83687ae40bfb8098
msgid "Enabled by default, can be disabled with ``--no extracting``."
msgstr "默认启用,可通过 ``--no extracting`` 关闭。"
#: ../../source/features.rst:83 c84af4829ecf4e3ca0e8ee7b41545291
#: ../../source/features.rst:83 3e586217eafe436fbd566dc44751ae72
msgid "Recursive search"
msgstr "递归搜索"
#: ../../source/features.rst:85 62f83ca52efa42e1abfab667eaa1c3e8
#: ../../source/features.rst:85 98a5a5561deb463ca15440072947bd04
msgid ""
"Maigret has the ability to scan account pages for :ref:`common "
"identifiers <supported-identifier-types>` and usernames found in links. "
@@ -129,15 +128,15 @@ msgstr ""
"和链接中出现的用户名。当用户在主页里贴出指向其它社交账号的链接时,Maigret "
"会自动识别并对这些账号发起新的搜索。在此过程中发现的全部信息,都会同时显示在命令行输出和生成的报告中。"
#: ../../source/features.rst:89 88d27a1d758f4ce5a9438650388db000
#: ../../source/features.rst:89 305f7071bf074687aaca8511531ea186
msgid "Enabled by default, can be disabled with ``--no-recursion``."
msgstr "默认启用,可通过 ``--no-recursion`` 关闭。"
#: ../../source/features.rst:122 17dec64423374faba021419561ffbd67
#: ../../source/features.rst:122 a1ec13a8b3fc4091a9d9aad8fc4536e2
msgid "Username permutations"
msgstr "用户名变体生成"
#: ../../source/features.rst:124 fbddaa705f9d4d43b8f753c671a7c06f
#: ../../source/features.rst:124 e4c00d35553049a9b73c4203e77df5f2
msgid ""
"Maigret can generate permutations of usernames. Just pass a few usernames"
" in the CLI and use ``--permute`` flag. Thanks to `@balestek "
@@ -146,49 +145,49 @@ msgstr ""
"Maigret 可以生成用户名的各种变体组合。只需在命令行传入几个用户名并加上 ``--permute`` 参数即可。感谢 `@balestek "
"<https://github.com/balestek>`_ 提供的想法和实现。"
#: ../../source/features.rst:149 8e73737273224c5db83f5c26f301e909
#: ../../source/features.rst:149 9dad12744e69420aa749fcf646f5fc8f
msgid "Reports"
msgstr "报告"
#: ../../source/features.rst:151 3a1366d6fa6549eb87c68ed60154f956
#: ../../source/features.rst:151 e70802a82a1f4c7d978558399b52c3ed
msgid ""
"Maigret currently supports HTML, PDF, TXT, XMind 8 mindmap, and JSON "
"reports."
msgstr "Maigret 目前支持 HTML、PDF、TXT、XMind 8 思维导图和 JSON 等格式的报告。"
#: ../../source/features.rst:153 e4c9654ef05c4431bddbfe36654d5950
#: ../../source/features.rst:153 f81c37a3ae254c37a69c1e8fad6a3fa0
msgid "HTML/PDF reports contain:"
msgstr "HTML / PDF 报告包含以下内容:"
#: ../../source/features.rst:155 3154eb754c154af1bfdc278a7129ff13
#: ../../source/features.rst:155 4c8b2dab41734e20b0266c76890bcd89
msgid "profile photo"
msgstr "头像"
#: ../../source/features.rst:156 fc3c96fc9c744f849c07f1d00d716fc3
#: ../../source/features.rst:156 c642caf9ffcf4136ae84e93354e19313
msgid "all the gathered personal info"
msgstr "已收集到的全部个人信息"
#: ../../source/features.rst:157 16214e18017942f8966cd55273911183
#: ../../source/features.rst:157 9744f896e29f47a09724faa36f4f126b
msgid ""
"additional information about supposed personal data (full name, gender, "
"location), resulting from statistics of all found accounts"
msgstr "基于所有已发现账号的统计,推测出的额外个人数据(真实姓名、性别、所在地)"
#: ../../source/features.rst:159 0a6ebe62f3b1499d9ae636affffe0baa
#: ../../source/features.rst:159 cdfdc97558fa4c278e462f6bcf9c2fd1
msgid ""
"Also, there is a short text report in the CLI output after the end of a "
"searching phase."
msgstr "此外,在搜索结束后,CLI 输出中也会附上一份简短的文本报告。"
#: ../../source/features.rst:162 af16c71f5d2a4415804baf234cb0d5d0
#: ../../source/features.rst:162 1389dbc9efba49b499252807bb1eb12b
msgid "XMind 8 mindmaps are incompatible with XMind 2022!"
msgstr "XMind 8 思维导图与 XMind 2022 不兼容!"
#: ../../source/features.rst:165 b806d9cc087444cb9d4b4d0f6224bd02
#: ../../source/features.rst:165 7855ecf44a5a4139ac24cfac44f659ff
msgid "AI analysis"
msgstr "AI 分析"
#: ../../source/features.rst:167 d23580679b6d4eed8e4c09d117242bcf
#: ../../source/features.rst:167 a7bc7ddbf02841a7acf6773a6aec39b5
msgid ""
"Maigret can produce a short, human-readable investigation summary on top "
"of the raw search results using the ``--ai`` flag. It builds the internal"
@@ -198,7 +197,7 @@ msgstr ""
"通过 ``--ai`` 参数,Maigret 可以基于原始搜索结果生成一份简短、易读的调查摘要。它会先构建一份内部 Markdown "
"报告,将其发送至一个 OpenAI 兼容的 chat completion 接口,并把模型的回复以流式方式直接输出到终端。"
#: ../../source/features.rst:178 53834075a9c847eca357f109a7cf8ed1
#: ../../source/features.rst:178 47a99e86b6ae4a1588e09ef7fd44ea0c
msgid ""
"The summary uses a fixed format with the most likely real name, location,"
" occupation, interests, languages, main website, username variants, "
@@ -210,7 +209,7 @@ msgstr ""
"该摘要采用固定格式,包含最可能的真实姓名、所在地、职业、兴趣、语言、主要使用的网站、用户名变体、出现过的平台数量、活跃年份、置信度评级,以及一份简短的后续线索清单。\\"
" ``--ai`` 启用期间,逐站点进度和简短文本报告都会被抑制,以让这份流式摘要成为主要输出。"
#: ../../source/features.rst:185 d2ca79ef0cbb4c0db9dd7a9dc033e670
#: ../../source/features.rst:185 85733bb1fa11414dba02e6f0627cb59e
msgid ""
"The endpoint, model, and API key are configured via ``settings.json`` "
"(``openai_api_key``, ``openai_model``, ``openai_api_base_url``) or the "
@@ -223,11 +222,11 @@ msgstr ""
"环境变量进行配置。可使用任意 OpenAI 兼容接口(Azure OpenAI、OpenRouter、本地推理服务等)。详情参见 :ref"
":`ai-analysis` 与 :ref:`settings`\\ 。"
#: ../../source/features.rst:192 581b6b0436ae4a5781eeb486e6588f26
#: ../../source/features.rst:192 8bba3181c9ec4009badf240909ff5ba2
msgid "Tags"
msgstr "标签"
#: ../../source/features.rst:194 b3e0b1b4404e4830aeb52cee70add04d
#: ../../source/features.rst:194 ac119f2a446745e19e1e0fc51f4ca717
msgid ""
"The Maigret sites database very big (and will be bigger), and it is maybe"
" an overhead to run a search for all the sites. Also, it is often hard to"
@@ -237,22 +236,22 @@ msgstr ""
"Maigret "
"的站点数据库已经很庞大(并且还会继续扩张),对所有站点都跑一遍搜索未必划算。同时,在调查某个具体人物时,也不容易判断哪些站点更值得关注。"
#: ../../source/features.rst:197 de59a8e8f58446629fb73e95a3ee98d3
#: ../../source/features.rst:197 c159b2fb30c0405d83ac51d2f7501c02
msgid ""
"Tags markup allows selecting a subset of sites by interests (photo, "
"messaging, finance, etc.) or by country. Tags of found accounts grouped "
"and displayed in the reports."
msgstr "标签体系允许按兴趣(摄影、即时通讯、金融等)或国家挑选站点子集。已发现账号上的标签会被分组,并显示在报告中。"
#: ../../source/features.rst:199 6a15bc91037e4e5382b9777dd48b216c
#: ../../source/features.rst:199 ed4a4e7541064e3687afe3712d64d77d
msgid "See full description :doc:`in the Tags Wiki page <tags>`."
msgstr "完整说明请参见 :doc:`标签页 <tags>`\\ 。"
#: ../../source/features.rst:202 899b6de94b0d42b1b81f46c4f37537df
#: ../../source/features.rst:202 96dc25e63f79489ba87542fdedd8123f
msgid "Censorship and captcha detection"
msgstr "审查和 CAPTCHA 检测"
#: ../../source/features.rst:204 e58d04de05374755928b836321eaf876
#: ../../source/features.rst:204 c05b9f998478422b9c480a2191f383dd
#, python-format
msgid ""
"Maigret can detect common errors such as censorship stub pages, "
@@ -263,25 +262,25 @@ msgstr ""
"Maigret 能够识别一些常见错误,例如审查占位页、CloudFlare 验证码页等等。如果在一次会话中某类错误超过了 3%,CLI "
"输出里就会打印一条警告,并附上用于改善表现、规避问题的建议。"
#: ../../source/features.rst:208 244105ddbc1a4938adff1cdec3eacacd
#: ../../source/features.rst:208 ad8458e0de4a4b019049b57af0ee2460
msgid "Retries"
msgstr "重试"
#: ../../source/features.rst:210 9057491007a24db09461ba415c21082c
#: ../../source/features.rst:210 64853719d00a4542a5a3c4e33e5fda82
msgid ""
"Maigret will do retries of the requests with temporary errors got "
"(connection failures, proxy errors, etc.)."
msgstr "对于遇到临时性错误(连接失败、代理错误等)的请求,Maigret 会进行重试。"
#: ../../source/features.rst:212 f271dec6df984fd1bdc0c82c5cfb19e8
#: ../../source/features.rst:212 712591ee78254a809879ad313f69220f
msgid "One attempt by default, can be changed with option ``--retries N``."
msgstr "默认尝试一次,可通过 ``--retries N`` 参数调整。"
#: ../../source/features.rst:215 a60841b531994f95830885b0002746e6
#: ../../source/features.rst:215 e20338540d6847bda34963bb81d8db8f
msgid "Database self-check"
msgstr "数据库自检"
#: ../../source/features.rst:217 799c17e506ad4192af4c506619da7710
#: ../../source/features.rst:217 37eb44c6abd440708fbbbd72785d0d9d
msgid ""
"Maigret includes a self-check mode (``--self-check``) that validates "
"every site in the database by looking up its known-claimed and known-"
@@ -291,7 +290,7 @@ msgstr ""
"Maigret 内置了一个自检模式(``--self-"
"check``),它会针对数据库中每个站点,分别查询已知被占用和已知未被占用的用户名,并验证检测结果是否符合预期。"
#: ../../source/features.rst:221 e79e8d1013f74190b47ff0ec7eb216d9
#: ../../source/features.rst:221 d1e875423487428381e6bc8fa17867bd
msgid ""
"The self-check is **error-resilient**: if an individual site check raises"
" an unexpected exception (e.g. a network error or a parsing failure), the"
@@ -304,7 +303,7 @@ msgstr ""
"**容错的**:如果某个站点的检查抛出意外异常(例如网络错误或解析失败),该错误会被捕获并记录为一个问题项,而其余站点会继续被检查,不会被中断。因此,即便使用"
" ``-a --self-check`` 检查上百个站点,该流程也总能顺利跑完。"
#: ../../source/features.rst:227 61c6a70829654399ae672d4be9703860
#: ../../source/features.rst:227 d75031d71d3941528aa337fbf56cbc8d
msgid ""
"Use ``--auto-disable`` together with ``--self-check`` to automatically "
"disable sites that fail checks. Without it, issues are only reported. Use"
@@ -315,21 +314,21 @@ msgstr ""
"可以把检查失败的站点自动禁用;不加该参数时,问题项只会被报告出来,而不会真正禁用。使用 ``--diagnose`` "
"则可以打印每个站点的详细诊断信息,包括检查类型、具体问题和修复建议。"
#: ../../source/features.rst:244 32d1a694a4894df589b223cadb2b50a8
#: ../../source/features.rst:244 97ad227189b34c2b8e80b9055dd0f48e
msgid "Archives and mirrors checking"
msgstr "归档站与镜像站检查"
#: ../../source/features.rst:246 ab9928e811e14c719e0c3ffe5e6b09b5
#: ../../source/features.rst:246 cab6bb0dc9e34379ae002ec46981c079
msgid ""
"The Maigret database contains not only the original websites, but also "
"mirrors, archives, and aggregators. For example:"
msgstr "Maigret 数据库中不仅包含原始网站,还包含镜像、归档和聚合站点。例如:"
#: ../../source/features.rst:248 2d146741016c460f88b7fd07fc2898f2
#: ../../source/features.rst:248 500d9a939ca14b2a981b1c9435cdcd73
msgid "`Picuki <https://www.picuki.com/>`_, Instagram mirror"
msgstr "`Picuki <https://www.picuki.com/>`_,Instagram 镜像"
#: ../../source/features.rst:249 ebb266ec7008400790a3c21e1d53932b
#: ../../source/features.rst:249 53f6db7eb7044cf294720e6239282686
msgid ""
"(no longer available) `Reddit BigData search <https://camas.github.io"
"/reddit-search/>`_"
@@ -337,22 +336,22 @@ msgstr ""
"(已不再可用)\\ `Reddit BigData search <https://camas.github.io/reddit-"
"search/>`_"
#: ../../source/features.rst:250 16c765fe6684414486f0c25dacfb9431
#: ../../source/features.rst:250 60124ff7e1e244d79c62846abb0cabbe
msgid "(no longer available) `Twitter shadowban <https://shadowban.eu/>`_ checker"
msgstr "(已不再可用)\\ `Twitter shadowban <https://shadowban.eu/>`_ 检查器"
#: ../../source/features.rst:252 dd8a821fe2cd406eb2f803dd06d15733
#: ../../source/features.rst:252 44ebab596acb41229bbe2ea989503b85
msgid ""
"It allows getting additional info about the person and checking the "
"existence of the account even if the main site is unavailable (bot "
"protection, captcha, etc.)"
msgstr "通过这些站点,可以获取关于目标人物的额外信息;即便主站点不可用(机器人防护、CAPTCHA 等),也仍能验证账号是否存在。"
#: ../../source/features.rst:257 ad050645ea194a0c8959fc56a0444251
#: ../../source/features.rst:257 ff0ab7835ec44e148d82397581bb4290
msgid "Cloudflare webgate bypass"
msgstr "Cloudflare webgate 绕过"
#: ../../source/features.rst:261 8c65965e0e1842ee98ca9b1e5a8a6898
#: ../../source/features.rst:261 99737687941844dfae996c262a4b1a85
msgid ""
"**Experimental feature.** The Cloudflare webgate is under active "
"development. The configuration schema, CLI flag behaviour, and the set of"
@@ -363,7 +362,7 @@ msgstr ""
"**实验性特性。** Cloudflare webgate 正处于积极开发阶段。配置项、CLI "
"参数行为以及经由其路由的站点集合都可能发生变化,不保证向后兼容。你可能会遇到一些不完善之处(CF 限速、求解器偶尔失败等),欢迎反馈以便逐步打磨。"
#: ../../source/features.rst:267 b878aff525094a388b38de75fd85a4b6
#: ../../source/features.rst:267 d67e2b25a2544422861e89866939e627
msgid ""
"Some sites sit behind a full Cloudflare JavaScript challenge or a CF "
"firewall hard block — these are tagged ``protection: "
@@ -375,7 +374,7 @@ msgstr ""
"``protection: [\"cf_js_challenge\"]`` 或 ``protection: [\"cf_firewall\"]``"
" 标记,并通常被禁用,因为 aiohttp 和 curl_cffi 都无法自行解出 JS 挑战。"
#: ../../source/features.rst:272 1100a4e9984f4157856ac897203dd9f3
#: ../../source/features.rst:272 887722f5e6c9401fb789e6ada2e62b2c
msgid ""
"Maigret can offload these checks to a local Chrome-based solver. Two "
"backends are supported, configured in ``settings.json`` under "
@@ -385,7 +384,7 @@ msgstr ""
"Maigret 可以把这类检查转交给本地的 Chrome 类求解器。目前支持两种后端,通过 ``settings.json`` 中的 "
"``cloudflare_bypass.modules`` 配置(第一个能连通的模块生效,后续模块作为兜底链依次尝试):"
#: ../../source/features.rst:277 7cc6522b5c0d492db9e63f7491da3cea
#: ../../source/features.rst:277 603de15a7c18429a94037f714af3e69f
msgid ""
"**FlareSolverr** (recommended). Runs a real Chrome instance and exposes a"
" JSON API. The upstream HTTP status, headers and final URL are preserved,"
@@ -396,7 +395,7 @@ msgstr ""
"状态码、响应头和最终 URL 都会被保留,因此 ``checkType: status_code`` 和 ``checkType: "
"response_url`` 在绕过模式下依然能正常工作。"
#: ../../source/features.rst:286 8586101867fc4191baf5f5bf1a9878bb
#: ../../source/features.rst:286 54d61596bbce43e8a82cb1141379a276
msgid ""
"**CloudflareBypassForScraping** (legacy fallback). Returns rendered HTML "
"only, so the upstream status code is lost — ``checkType: message`` keeps "
@@ -405,24 +404,33 @@ msgstr ""
"**CloudflareBypassForScraping**\\ (旧版兜底)。只返回渲染后的 HTML,因此上游真实状态码会丢失 —— "
"``checkType: message`` 仍然可用,但 ``status_code`` 类检查会失准(成功时会被视为 200)。"
#: ../../source/features.rst:290 204a36006bb14825a7acbbe54faf8f0c
#: ../../source/features.rst:290 d6f5bd6b3ac043e1a9153827b0492c00
msgid "Activate the bypass either with the CLI flag::"
msgstr "启用绕过有两种方式,一是命令行参数::"
#: ../../source/features.rst:294 0285b3904ee545c59536eb8566191c95
#: ../../source/features.rst:294 8a9237637b414665bc1a30722539d650
msgid ""
"or by setting ``cloudflare_bypass.enabled`` to ``true`` in "
"``settings.json``. The bypass only fires for sites whose ``protection`` "
"field intersects ``cloudflare_bypass.trigger_protection`` (default "
"``[\"cf_js_challenge\", \"cf_firewall\", \"webgate\"]``); all other sites"
" use the normal aiohttp / curl_cffi path."
"``settings.json``. The web UI (``python -m maigret.web.app``) reads the "
"same setting — there is no separate toggle in the form, so flipping "
"``enabled`` is what activates the bypass for browser-driven runs."
msgstr ""
"二是在 ``settings.json`` 中将 ``cloudflare_bypass.enabled`` 设为 ``true``\\ "
"。该绕过只对 ``protection`` 字段与 ``cloudflare_bypass.trigger_protection``\\ (默认 "
"``[\"cf_js_challenge\", \"cf_firewall\", "
"\"webgate\"]``)有交集的站点生效;其它站点仍走常规的 aiohttp / curl_cffi 路径。"
"在 ``settings.json`` 中将 ``cloudflare_bypass.enabled`` 设为 ``true``"
"Web 界面(``python -m maigret.web.app``)读取的是同一份配置 —— 表单中"
"没有单独的开关,因此切换 ``enabled`` 就是浏览器场景下启用绕过的唯一方式。"
#: ../../source/features.rst:300 60fdeed8e1c8458bb584e5abe4c524a5
#: ../../source/features.rst:299 8cd7c8ef31e845cfa7bef77caa8b4a47
msgid ""
"The bypass only fires for sites whose ``protection`` field intersects "
"``cloudflare_bypass.trigger_protection`` (default ``[\"cf_js_challenge\","
" \"cf_firewall\", \"webgate\"]``); all other sites use the normal aiohttp"
" / curl_cffi path."
msgstr ""
"该绕过只对 ``protection`` 字段与 ``cloudflare_bypass.trigger_protection``"
"\\ (默认 ``[\"cf_js_challenge\", \"cf_firewall\", \"webgate\"]``)有交集"
"的站点生效;其它站点仍走常规的 aiohttp / curl_cffi 路径。"
#: ../../source/features.rst:304 98d59ab2376c44fc89adf426a612366d
msgid ""
"If all configured modules are unreachable, affected sites get an UNKNOWN "
"status with an actionable error pointing at the first module's URL — the "
@@ -431,7 +439,7 @@ msgstr ""
"如果所有配置的模块都不可达,受影响的站点会被标记为 UNKNOWN,并附上一条可操作的错误信息,指向首个模块的 URL —— "
"绝大多数情况下,只需把 FlareSolverr 容器跑起来就能解决。"
#: ../../source/features.rst:304 79fdbe6283274bb39d174b5b06f30251
#: ../../source/features.rst:308 2ee4a6ee33f847ce87472cd442bcd18e
msgid ""
"FlareSolverr session reuse is automatic: Maigret pins a single ``session:"
" <session_prefix>-<pid>`` per run, so cf_clearance cookies are shared "
@@ -442,60 +450,60 @@ msgstr ""
"<session_prefix>-<pid>``,这样对同一域名的多次检查就会共享 cf_clearance cookie(后续对该主机的请求会快"
" 510 倍)。"
#: ../../source/features.rst:310 50e0d736536e431ca335765c839c23a2
#: ../../source/features.rst:314 3f43bfb6c70e48e285a7cc862d7988e6
msgid "Activation"
msgstr "激活机制"
#: ../../source/features.rst:311 0cae44249d6243bf929b4c6ee402df8b
#: ../../source/features.rst:315 f3fbc5aaaadc475cb27e6050ed392c72
msgid ""
"The activation mechanism helps make requests to sites requiring "
"additional authentication like cookies, JWT tokens, or custom headers."
msgstr "激活机制用于向那些需要额外认证(cookie、JWT token、自定义请求头等)的站点发起请求。"
#: ../../source/features.rst:313 7e2bcbdc83f84cb183bc15bed13a315d
#: ../../source/features.rst:317 8904ac193b06468aa8c2a0eac03387f0
msgid "It works by implementing a custom function that:"
msgstr "其实现方式是通过一个自定义函数,完成以下三步:"
#: ../../source/features.rst:315 96d50906bb3f4fd38eb20ceeca581706
#: ../../source/features.rst:319 9ff5a4ab39284a55aed726ed75aebe6e
msgid "Makes a specialized HTTP request to a specific website endpoint"
msgstr "向某个特定网站端点发起一个专门的 HTTP 请求"
#: ../../source/features.rst:316 7ac14f5c64c6423d9a677013143ab93b
#: ../../source/features.rst:320 c96edc4ff8654074b71ce45af7fa84c1
msgid "Processes the response"
msgstr "处理响应内容"
#: ../../source/features.rst:317 f570a98e68314397a84ad404efa6adb0
#: ../../source/features.rst:321 418b7eb1dd824175b3fad35d3ea9d33c
msgid "Updates the headers/cookies for that site in the local Maigret database"
msgstr "在本地 Maigret 数据库中更新该站点对应的请求头/cookie"
#: ../../source/features.rst:319 d399ee0fa3a3466792a51a418f6bc12a
#: ../../source/features.rst:323 30f2c88b051546539456ce0c98957a82
msgid ""
"Since activation only triggers after encountering specific errors, a "
"retry (or another Maigret run) is needed to obtain a valid response with "
"the updated authentication."
msgstr "由于激活只在遇到特定错误后才会触发,因此要拿到使用新认证信息的有效响应,还需要再触发一次重试(或重新运行一次 Maigret)。"
#: ../../source/features.rst:321 a8c2255fea80429b8d50db28a5e5c482
#: ../../source/features.rst:325 9da1a6a8d5d848e7a9987a6e864d6da5
msgid ""
"The activation mechanism is enabled by default, and cannot be disabled at"
" the moment."
msgstr "激活机制默认启用,目前无法关闭。"
#: ../../source/features.rst:323 92b566a8ed624f179a1bf92f92276078
#: ../../source/features.rst:327 0573ae8856364e819e56931340bc6fb7
msgid "See for more details in Development section :ref:`activation-mechanism`."
msgstr "更多细节请参见开发文档中的 :ref:`activation-mechanism` 一节。"
#: ../../source/features.rst:328 07d22d7c68294f60bb9338352c0f5317
#: ../../source/features.rst:332 efe6f17c461a44e099b06d44a597b5b2
msgid "Extraction of information from account pages"
msgstr "从账号页面抽取信息"
#: ../../source/features.rst:330 d6278ffe262349838922c615cb64b539
#: ../../source/features.rst:334 c820edcca1184d4382c8a57eded6cc47
msgid ""
"Maigret can parse URLs and content of web pages by URLs to extract info "
"about account owner and other meta information."
msgstr "Maigret 可以根据给定 URL 解析网页地址及其内容,抽取账号所有者及其它元信息。"
#: ../../source/features.rst:332 0cf168608d0e41e0a5cf39f1be547372
#: ../../source/features.rst:336 540ba0732e5348e0838f7cdafcdee244
msgid ""
"You must specify the URL with the option ``--parse``, it's can be a link "
"to an account or an online document. List of supported sites `see here "
@@ -504,7 +512,7 @@ msgstr ""
"需要使用 ``--parse`` 选项指定 URL,可以是某个账号的链接,也可以是在线文档的链接。支持的站点列表请\\ `查看此处 "
"<https://github.com/soxoj/socid-extractor#sites>`_。"
#: ../../source/features.rst:334 2f78bb887c3c432890a69b15f6c37470
#: ../../source/features.rst:338 7db26f80206f49e4ac99971c8829c8ef
msgid ""
"After the end of the parsing phase, Maigret will start the search phase "
"by :doc:`supported identifiers <supported-identifier-types>` found "
@@ -513,11 +521,11 @@ msgstr ""
"解析阶段结束后,Maigret 会根据从中找到的 :doc:`受支持标识符 <supported-identifier-types>`\\ "
"(用户名、ID 等)进入搜索阶段。"
#: ../../source/features.rst:362 2946ce8afc394246b8f780f51bd86b19
#: ../../source/features.rst:366 a1bd40f9e8a24be2b76cb9fbdb3c03e1
msgid "Simple API"
msgstr "简单 API"
#: ../../source/features.rst:364 6483467ea4d146148ede1d9d71ce727c
#: ../../source/features.rst:368 c032748ecb4847ecb5590a4fa6629ba0
msgid ""
"Maigret can be easily integrated with the use of Python package `maigret "
"<https://pypi.org/project/maigret/>`_."
@@ -525,7 +533,7 @@ msgstr ""
"借助 Python 包 `maigret <https://pypi.org/project/maigret/>`_,可以很方便地把 "
"Maigret 集成到自己的项目中。"
#: ../../source/features.rst:366 a12e865e64e54d4d949680aa3db2d51e
#: ../../source/features.rst:370 115fa7827cea4dc68871f2a516999f7d
msgid ""
"Example: the community `Telegram bot <https://github.com/soxoj/maigret-"
"tg-bot>`_"
+161 -142
View File
@@ -6,7 +6,7 @@ msgid ""
msgstr ""
"Project-Id-Version: Maigret 0.6\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2026-05-22 20:48+0200\n"
"POT-Creation-Date: 2026-05-25 18:02+0200\n"
"PO-Revision-Date: 2026-05-22 21:00+0200\n"
"Last-Translator: \n"
"Language: zh_CN\n"
@@ -17,296 +17,308 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n"
"Generated-By: Babel 2.18.0\n"
#: ../../source/settings.rst:4 c390d741629a40d28a83af5434f8cbeb
#: ../../source/settings.rst:4 fe76c47d0aa1445c891f588fa40b146c
msgid "Settings"
msgstr "配置"
#: ../../source/settings.rst:7 85c1b59773954c879b7ec2854d9fec0f
#: ../../source/settings.rst:7 53c34f2bdb7d4be498b654113d7d6231
msgid "The settings system is under development and may be subject to change."
msgstr "配置系统仍在开发中,后续可能发生变化。"
#: ../../source/settings.rst:9 ddb12727febb4a9ba5511f6c53f5f040
#: ../../source/settings.rst:9 4d4fd09541ce4883bfcdc64d646caf16
msgid ""
"Options are also configurable through settings files. See `settings JSON "
"file "
"<https://github.com/soxoj/maigret/blob/main/maigret/resources/settings.json>`_"
" for the list of currently supported options."
msgstr ""
"各项选项也可以通过配置文件进行设置。当前支持的完整选项列表请参见 `settings JSON 文件 <https://github.com/soxoj/maigret/blob/main/maigret/resources/settings.json>`_。"
"各项选项也可以通过配置文件进行设置。当前支持的完整选项列表请参见 `settings JSON 文件 "
"<https://github.com/soxoj/maigret/blob/main/maigret/resources/settings.json>`_。"
#: ../../source/settings.rst:13 f7de8fdd9407425d9164de1696eb9a2c
#: ../../source/settings.rst:13 0c0a9cd3c69b41c1b577466ebc33e36d
msgid ""
"After start Maigret tries to load configuration from the following "
"sources in exactly the same order:"
msgstr ""
"启动后,Maigret 会\ **按以下顺序**\ 依次尝试从这些位置加载配置:"
msgstr "启动后,Maigret 会\\ **按以下顺序**\\ 依次尝试从这些位置加载配置:"
#: ../../source/settings.rst:26 75bc73e45f7a4b41a13de7b62f03e710
#: ../../source/settings.rst:26 15ad0a7667b246b081ad08074d479d8d
msgid ""
"Missing any of these files is not an error. If the next settings file "
"contains already known option, this option will be rewrited. So it is "
"possible to make custom configuration for different users and "
"directories."
msgstr ""
"上述文件中任何一个不存在都不算错误。如果后一个配置文件包含了已经出现过的"
"选项,该选项就会被覆盖。因此你可以针对不同用户和不同目录设置不同的自定义"
"配置。"
msgstr "上述文件中任何一个不存在都不算错误。如果后一个配置文件包含了已经出现过的选项,该选项就会被覆盖。因此你可以针对不同用户和不同目录设置不同的自定义配置。"
#: ../../source/settings.rst:34 3b458bc88d694d769ab609dd698a840a
#: ../../source/settings.rst:34 018bbabf2f414554a59579239aa70d06
msgid "Database auto-update"
msgstr "数据库自动更新"
#: ../../source/settings.rst:36 e538967a9d634e48bd61d789ba23e6f3
#: ../../source/settings.rst:36 652f6ed1943a4bbf95290f956eb7b28a
msgid ""
"Maigret ships with a bundled site database, but it gets outdated between "
"releases. To keep the database current, Maigret automatically checks for "
"updates on startup."
msgstr ""
"Maigret 自带一份站点数据库,但它会随着新版本发布而逐渐过时。为了保持数据库"
"是最新的,Maigret 在启动时会自动检查更新。"
msgstr "Maigret 自带一份站点数据库,但它会随着新版本发布而逐渐过时。为了保持数据库是最新的,Maigret 在启动时会自动检查更新。"
#: ../../source/settings.rst:38 d324c3899a824d87b25596a4d57435ca
#: ../../source/settings.rst:38 c9681e2aab35468e9af30b1b684301a0
msgid "**How it works:**"
msgstr "**工作机制:**"
#: ../../source/settings.rst:40 f8e9ee638abc4864b6af65c023e3e5b8
#: ../../source/settings.rst:40 def91bc9f8e84dcebce7e2fa602ae0f5
msgid ""
"On startup, Maigret checks if more than 24 hours have passed since the "
"last update check."
msgstr ""
"启动时,Maigret 会检查距离上次更新检查是否已超过 24 小时。"
msgstr "启动时,Maigret 会检查距离上次更新检查是否已超过 24 小时。"
#: ../../source/settings.rst:41 e38f9607201a4475996b5005112e1c0e
#: ../../source/settings.rst:41 dfab33e815164c86a4ebe0e7e78ed6ee
msgid ""
"If so, it fetches a lightweight metadata file (~200 bytes) from GitHub to"
" see if a newer database is available."
msgstr ""
"如果超过了,就从 GitHub 拉取一份轻量元数据文件(约 200 字节),查看是否有"
"更新版本的数据库。"
msgstr "如果超过了,就从 GitHub 拉取一份轻量元数据文件(约 200 字节),查看是否有更新版本的数据库。"
#: ../../source/settings.rst:42 baf3af441dc74128a2b754ccbffa5f4e
#: ../../source/settings.rst:42 209b0131bfdd48c2b68e7088c2cb6014
msgid ""
"If a newer, compatible database exists, Maigret downloads it to "
"``~/.maigret/data.json`` and uses it instead of the bundled copy."
msgstr ""
"如果存在更新且兼容的数据库,Maigret 会把它下载到 "
"``~/.maigret/data.json``,并用它替代内置的版本。"
msgstr "如果存在更新且兼容的数据库,Maigret 会把它下载到 ``~/.maigret/data.json``,并用它替代内置的版本。"
#: ../../source/settings.rst:43 95539bb0b235488baf6edfac2a6fbbc8
#: ../../source/settings.rst:43 d8aa5049e4ee40929e746b6f5b4c6be8
msgid ""
"If the download fails or the new database is incompatible with your "
"Maigret version, the bundled database is used as a fallback."
msgstr ""
"如果下载失败,或新数据库与你的 Maigret 版本不兼容,就回退到内置数据库。"
msgstr "如果下载失败,或新数据库与你的 Maigret 版本不兼容,就回退到内置数据库。"
#: ../../source/settings.rst:45 6f412fc0cf87469c8742681587d1dd29
#: ../../source/settings.rst:45 26696d84d93342dfbd89b6ca614f29a5
msgid ""
"The downloaded database has **higher priority** than the bundled one — it"
" replaces, not overlays."
msgstr ""
"下载下来的数据库\ **优先级高于**\ 内置数据库 —— 它是替换关系,而不是叠加。"
msgstr "下载下来的数据库\\ **优先级高于**\\ 内置数据库 —— 它是替换关系,而不是叠加。"
#: ../../source/settings.rst:47 fe13cb78d21944ee86c63919042591c8
#: ../../source/settings.rst:47 93ce61948c464569a7efdd07ae269fb2
msgid "**Status messages** are printed only when an action occurs:"
msgstr "**状态消息**\ 仅在实际发生某种动作时才会打印:"
msgstr "**状态消息**\\ 仅在实际发生某种动作时才会打印:"
#: ../../source/settings.rst:56 24e10dd219b6407ebda94bd3bf48b162
#: ../../source/settings.rst:56 0845742ea7ed4b44a6194a7a9f8faca2
msgid "**Forcing an update:**"
msgstr "**强制更新:**"
#: ../../source/settings.rst:58 872077b7b1164f87b59d385a170f7317
#: ../../source/settings.rst:58 ee8fcb44764949dcb422d9523f203837
msgid ""
"Use the ``--force-update`` flag to check for updates immediately, "
"ignoring the check interval:"
msgstr ""
"使用 ``--force-update`` 参数会忽略检查间隔,立刻检查更新:"
msgstr "使用 ``--force-update`` 参数会忽略检查间隔,立刻检查更新:"
#: ../../source/settings.rst:64 1d278924d02a4df49e5532f9d97ef0e2
#: ../../source/settings.rst:64 abcac12715f6447283a54b1d21eb3f26
msgid ""
"The update happens at startup, then the search continues normally with "
"the freshly downloaded database."
msgstr ""
"更新只在启动时进行,完成后即用新下载的数据库继续执行正常搜索。"
msgstr "更新只在启动时进行,完成后即用新下载的数据库继续执行正常搜索。"
#: ../../source/settings.rst:66 bb9d37cbb1c34d4e92363252d84e48ec
#: ../../source/settings.rst:66 8dfdb9ddb94742d6916accf6a637b621
msgid "**Disabling auto-update:**"
msgstr "**禁用自动更新:**"
#: ../../source/settings.rst:68 10eaed158bc94a3086a3dabfb00b86b2
#: ../../source/settings.rst:68 e63059a385e042989dbffc8faa6620be
msgid "Use the ``--no-autoupdate`` flag to skip the update check entirely:"
msgstr "使用 ``--no-autoupdate`` 参数可以完全跳过更新检查:"
#: ../../source/settings.rst:74 13eb1b9bc7ff4414a1a561fbff005cfb
#: ../../source/settings.rst:74 4538e0b662e74117ac60feb580ea14cf
msgid "Or set it permanently in ``~/.maigret/settings.json``:"
msgstr "或者在 ``~/.maigret/settings.json`` 中永久设置:"
#: ../../source/settings.rst:82 37c3a67aa7724ec5849c2f4cfc4b76d4
#: ../../source/settings.rst:82 01fb39cf9f6648cb818421edd235e9bd
msgid ""
"This is recommended for **Docker containers**, **CI pipelines**, and "
"**air-gapped environments**."
msgstr ""
"该选项推荐用于 **Docker 容器**\ 、\ **CI 流水线**\ 以及\ **离线隔离环境**\ 。"
msgstr "该选项推荐用于 **Docker 容器**\\ 、\\ **CI 流水线**\\ 以及\\ **离线隔离环境**\\ 。"
#: ../../source/settings.rst:84 a168f36ac5f14c979cec5dc24a649245
#: ../../source/settings.rst:84 4d8f3a1e5313475ab522313771b11096
msgid "**Configuration options** (in ``settings.json``):"
msgstr "**配置项**\ (位于 ``settings.json``):"
msgstr "**配置项**\\ (位于 ``settings.json``):"
#: ../../source/settings.rst:90 ../../source/settings.rst:206
#: 65aee9ef96d44ff4a5dcf3cc4c3cd7ae d3c2c0cf24c24046ba731c1dc3aa90a6
#: ../../source/settings.rst:90 ../../source/settings.rst:242
#: 8ee43c194a614f57b2f10cf306622d9d 9bce6a59ddf14978a8a6b536b266d6cb
msgid "Setting"
msgstr "选项"
#: ../../source/settings.rst:91 ../../source/settings.rst:207
#: 2b777384ccc84eabb71ccbbd9136ae70 ecaf3eef672e4b2e8f45030decfa8c41
#: ../../source/settings.rst:91 ../../source/settings.rst:243
#: 0961df2fea32498a82984fcd2a6cd428 e8446230ddf34848bbbc331cfefb4745
msgid "Default"
msgstr "默认值"
#: ../../source/settings.rst:92 ../../source/settings.rst:147
#: ../../source/settings.rst:208 80aeb637a3dd4d729d276a989cb24d0a
#: a4edc383a0004df693e18734690b8306 e97723cec40d4e67a7f9485589ed8962
#: ../../source/settings.rst:92 ../../source/settings.rst:183
#: ../../source/settings.rst:244 2dbd3a0f5c00431a908b42aec54f648c
#: 6d42f72550974316980c6bf1806ff29c e84d99a18c264735a2adfa5099d4b0fd
msgid "Description"
msgstr "说明"
#: ../../source/settings.rst:93 b2217c7eaa2547dca6d93cea931c26de
#: ../../source/settings.rst:93 ffec75c5cdea4c9aa0c69125f639339a
msgid "``no_autoupdate``"
msgstr "``no_autoupdate``"
#: ../../source/settings.rst:94 6119dbf49ef344d58ffbf2bbfbdb944a
#: ../../source/settings.rst:94 16b9c70c0b6a412d9bde98cb2a60e216
msgid "``false``"
msgstr "``false``"
#: ../../source/settings.rst:95 d47676ca870649b19c79e5d1bdaacbfa
#: ../../source/settings.rst:95 2381445bb42b40fdacaebd43988daa49
msgid "Disable auto-update entirely"
msgstr "完全禁用自动更新"
#: ../../source/settings.rst:96 e14808e21c5b4051bb1bc7ebd2e3f70d
#: ../../source/settings.rst:96 c6ad3238aab14a3d9070588c11ae8ed4
msgid "``autoupdate_check_interval_hours``"
msgstr "``autoupdate_check_interval_hours``"
#: ../../source/settings.rst:97 5195c80256c14e778a3cf45f8dd0a4b4
#: ../../source/settings.rst:97 6cf231184c7740ffb6e8116d11387e4f
msgid "``24``"
msgstr "``24``"
#: ../../source/settings.rst:98 5042d467e19542f18549b80dd7a8f855
#: ../../source/settings.rst:98 3c1ea4469c8d425492ec6cccce8aac55
msgid "How often to check for updates (in hours)"
msgstr "检查更新的间隔(单位:小时)"
#: ../../source/settings.rst:99 b52e153b8fa943c7bddfc730b2465564
#: ../../source/settings.rst:99 efb1d0e86cac42c3adf1f3ef4c76c91a
msgid "``db_update_meta_url``"
msgstr "``db_update_meta_url``"
#: ../../source/settings.rst:100 c6b3db2ba4534c8ba25f80a1d4d61818
#: ../../source/settings.rst:100 1a0cf0e2a938494689e926cdf7f7ac9e
msgid "GitHub raw URL"
msgstr "GitHub raw URL"
#: ../../source/settings.rst:101 fd5b0e773d5049c2b29f0b19acb02216
#: ../../source/settings.rst:101 25a72fbd4eb74ff7b5b0b28e8e43addf
msgid "URL of the metadata file (for custom mirrors)"
msgstr "元数据文件的 URL(用于自建镜像)"
#: ../../source/settings.rst:103 96e490bb647447f0afce8e2501cb926b
#: ../../source/settings.rst:103 4a02e3e5680c477d8a03b2c5a1b5ca8c
msgid ""
"**Using a custom database** with ``--db`` always skips auto-update — you "
"are explicitly choosing your data source."
msgstr ""
"使用 ``--db`` 指定自定义数据库时,\ **总是会跳过**\ 自动更新 —— 因为你已经"
"明确选择了数据源。"
msgstr "使用 ``--db`` 指定自定义数据库时,\\ **总是会跳过**\\ 自动更新 —— 因为你已经明确选择了数据源。"
#: ../../source/settings.rst:106 b5544b3530334be19b1888f225cdb091
#: ../../source/settings.rst:106 f7ea5acf3a354a2681d7a150e277f086
msgid "Cloudflare webgate"
msgstr "Cloudflare webgate"
#: ../../source/settings.rst:110 2ae8dfcef81846a887bfc0321b341066
#: ../../source/settings.rst:110 9a059aba51304c1aa1c47c4e681511e6
msgid ""
"**Experimental.** The ``cloudflare_bypass`` block is under active "
"development; field names, defaults, and the trigger-protection routing "
"rules may change without backwards-compatibility guarantees."
msgstr ""
"**实验特性。** ``cloudflare_bypass`` 这一节仍在积极开发中;字段名、默认值"
"以及 trigger-protection 的路由规则都可能发生变化,不保证向后兼容。"
"**实验特性。** ``cloudflare_bypass`` 这一节仍在积极开发中;字段名、默认值以及 trigger-protection "
"的路由规则都可能发生变化,不保证向后兼容。"
#: ../../source/settings.rst:114 ab108db50bd244cf8c5dc08ca12227dc
#: ../../source/settings.rst:114 3121d43837664c1f9818c7099732eb09
msgid ""
"The ``cloudflare_bypass`` block in ``settings.json`` configures the "
"optional bypass described in :ref:`cloudflare-bypass`. Default value:"
"optional bypass described in :ref:`cloudflare-bypass`. The same block is "
"honoured by the CLI, the Python API, and the web UI (``python -m "
"maigret.web.app``); set ``enabled: true`` once and every entry point "
"routes cf-protected sites through the solver."
msgstr ""
"``settings.json`` 中的 ``cloudflare_bypass`` 配置块用于配置 "
":ref:`cloudflare-bypass` 所述的可选绕过机制。默认值如下:"
":ref:`cloudflare-bypass` 所述的可选绕过机制。CLI、Python API 以及 Web 界面"
"(``python -m maigret.web.app``)都会读取同一份配置:只需将 ``enabled`` 设为"
" ``true``,所有入口都会把受 cf 保护的站点转发给求解器。"
#: ../../source/settings.rst:140 293518d17b904d058aedfa946717d649
#: ../../source/settings.rst:120 a98ec36b3f954c30af38363e9bea6ec3
msgid ""
"**Minimal FlareSolverr setup.** Start the solver in Docker, then drop the"
" following snippet into ``~/.maigret/settings.json`` (or any path listed "
"in :ref:`settings`):"
msgstr ""
"**FlareSolverr 最小化配置。** 先用 Docker 启动求解器,然后把下面这段配置"
"写入 ``~/.maigret/settings.json``\\ (或 :ref:`settings` 中列出的任意路径):"
#: ../../source/settings.rst:145 d8dc102a6ea247d991b6c09f917bc37a
msgid ""
"That is enough — ``session_prefix`` and ``trigger_protection`` fall back "
"to sensible defaults (``\"maigret\"`` and ``[\"cf_js_challenge\", "
"\"cf_firewall\", \"webgate\"]`` respectively). On the next run, Maigret "
"logs ``Cloudflare webgate active: ...`` and routes matching sites through"
" the solver."
msgstr ""
"这样就够了 —— ``session_prefix`` 和 ``trigger_protection`` 会回退到合理的"
"默认值(分别为 ``\"maigret\"`` 和 "
"``[\"cf_js_challenge\", \"cf_firewall\", \"webgate\"]``)。下次运行时,"
"Maigret 会输出 ``Cloudflare webgate active: ...`` 日志,并把命中的站点"
"路由到求解器。"
#: ../../source/settings.rst:151 bfff9d4907664fc3862b5a6a20da88be
msgid "Default value (full schema with every supported field):"
msgstr "默认值(包含全部受支持字段的完整结构):"
#: ../../source/settings.rst:176 46b6a3845ba548aa8823e049281bda6d
msgid "**Fields.**"
msgstr "**字段说明。**"
#: ../../source/settings.rst:146 2ca7704b61aa4258b0cdce8157f9ce6f
#: ../../source/settings.rst:182 bad54b56ab2945058697d7054a6055fa
msgid "Field"
msgstr "字段"
#: ../../source/settings.rst:148 66779ca136dc4c7bb02a693f7a8e24b2
#: ../../source/settings.rst:184 610f1da5f28040079ae2bcb10618573c
msgid "``enabled``"
msgstr "``enabled``"
#: ../../source/settings.rst:149 74155cf90696425e9845ce3b54b48ac3
#: ../../source/settings.rst:185 c3149bfa418c4e3b95dde5611ef4717b
msgid ""
"When ``true``, the bypass is active for every run; when ``false`` (the "
"default), it activates only on ``--cloudflare-bypass``."
msgstr ""
"为 ``true`` 时,每次运行都会启用绕过;为 ``false``\ (默认)时,仅在传入 "
"``--cloudflare-bypass`` 时才启用。"
"为 ``true`` 时,每次运行都会启用绕过;为 ``false``\\ (默认)时,仅在传入 ``--cloudflare-bypass`` "
"时才启用。"
#: ../../source/settings.rst:151 a7643702bf5f428bb8ee0cd317d3126e
#: ../../source/settings.rst:187 5c92e71e8ec144be83f8abbca6e37d01
msgid "``trigger_protection``"
msgstr "``trigger_protection``"
#: ../../source/settings.rst:152 c33771acb2ba4f098c6dfc1aa53d4744
#: ../../source/settings.rst:188 38557548995949a5b8121d81ffc51178
msgid ""
"List of ``site.protection`` values that route a check through the "
"webgate. Sites whose protection is empty or doesn't intersect this list "
"use the default (aiohttp / curl_cffi) checker."
msgstr ""
"一个 ``site.protection`` 值的列表;命中其中任何一个时,检查请求都会经由"
"webgate 转发。\ ``protection`` 为空、或与本列表无交集的站点,仍使用默认的"
"检查器(aiohttp / curl_cffi)。"
"一个 ``site.protection`` 值的列表;命中其中任何一个时,检查请求都会经由webgate 转发。\\ "
"``protection`` 为空、或与本列表无交集的站点,仍使用默认的检查器(aiohttp / curl_cffi)。"
#: ../../source/settings.rst:155 9fc5f3ea49664010af05dbea49ad633b
#: ../../source/settings.rst:191 4b93a27e05b34050837eccffbcb40bed
msgid "``session_prefix``"
msgstr "``session_prefix``"
#: ../../source/settings.rst:156 0b6e098ac4314fa2ac21955e839f232e
#: ../../source/settings.rst:192 c54f79f2b5ca4c42805b948cbbb3c3d2
msgid ""
"Prefix for the FlareSolverr ``session`` field. Maigret appends the "
"process PID so concurrent runs don't collide. Reusing a session caches "
"cf_clearance between checks of the same domain."
msgstr ""
"FlareSolverr ``session`` 字段的前缀。Maigret 会在其后追加进程 PID,避免并发"
"运行相互冲突。复用同一个 session 会在对同一域名的多次检查之间缓存 "
"cf_clearance。"
"FlareSolverr ``session`` 字段的前缀。Maigret 会在其后追加进程 PID,避免并发运行相互冲突。复用同一个 "
"session 会在对同一域名的多次检查之间缓存 cf_clearance。"
#: ../../source/settings.rst:159 f810495bb01a415da4400ccfd553f6d3
#: ../../source/settings.rst:195 9742c805b326433aac2ad92e1e48a880
msgid "``modules``"
msgstr "``modules``"
#: ../../source/settings.rst:160 96a91e5c374f4e21a710b75b9e4bff5d
#: ../../source/settings.rst:196 8c7a26caf24040fc9afce140b739ba89
msgid ""
"Ordered list of backend modules. The first reachable module handles the "
"check; later ones serve as a fallback chain."
msgstr ""
"后端模块的有序列表。第一个能连通的模块负责处理该检查,后续模块作为兜底链。"
msgstr "后端模块的有序列表。第一个能连通的模块负责处理该检查,后续模块作为兜底链。"
#: ../../source/settings.rst:163 15176838fce043c180896ec24f8c3e12
#: ../../source/settings.rst:199 262a0c13a9ae4815962b16733ef6016e
msgid "**Module methods.**"
msgstr "**模块方法。**"
#: ../../source/settings.rst:165 227d24158d2643b7a5f529b69d909507
#: ../../source/settings.rst:201 a3145c584a0e453aac0ca51f67ee12db
msgid ""
"``json_api`` — FlareSolverr-compatible POST endpoint at ``url``. "
"Preserves real upstream HTTP status, headers and final URL. Optional "
"``max_timeout_ms`` (default ``60000``) is the per-request budget the "
"solver is allowed to spend on the JS challenge."
msgstr ""
"``json_api`` —— 在 ``url`` 上提供的 FlareSolverr 兼容 POST 接口。会保留上游"
"真实的 HTTP 状态码、响应头和最终 URL。可选字段 ``max_timeout_ms``\ (默认 "
"``60000``)是允许求解器在 JS 挑战上花费的单次请求时间预算。"
"``json_api`` —— 在 ``url`` 上提供的 FlareSolverr 兼容 POST 接口。会保留上游真实的 HTTP "
"状态码、响应头和最终 URL。可选字段 ``max_timeout_ms``\\ (默认 ``60000``)是允许求解器在 JS "
"挑战上花费的单次请求时间预算。"
#: ../../source/settings.rst:169 1db9fddba6a743149e97c415f66532fd
#: ../../source/settings.rst:205 fe03ccdb70144c77adc1b7280d9f71ca
#, python-brace-format
msgid ""
"``url_rewrite`` — legacy CloudflareBypassForScraping endpoint. The "
@@ -315,84 +327,81 @@ msgid ""
" status_code`` and ``response_url`` checks misfire under this method "
"(treated as a synthetic HTTP 200 on success)."
msgstr ""
"``url_rewrite`` —— 旧版 CloudflareBypassForScraping 接口。\ ``url`` 中必须"
"包含 ``{url}`` 占位符;原始探测 URL 会被 URL 编码后代入。该方式仅返回渲染后"
"的 HTML —— 因此在此方法下,\ ``checkType: status_code`` 和 ``response_url`` "
"两类检查会失准(成功时会被当作一个虚构的 HTTP 200)。"
"``url_rewrite`` —— 旧版 CloudflareBypassForScraping 接口。\\ ``url`` 中必须包含 "
"``{url}`` 占位符;原始探测 URL 会被 URL 编码后代入。该方式仅返回渲染后的 HTML —— 因此在此方法下,\\ "
"``checkType: status_code`` 和 ``response_url`` 两类检查会失准(成功时会被当作一个虚构的 HTTP "
"200)。"
#: ../../source/settings.rst:175 663c371e2b7b4ebc832be8d0e2f3b773
#: ../../source/settings.rst:211 7dd51af2a40f4b64ab35e75a7291ad88
msgid "**Optional ``proxy`` field (``json_api`` only).**"
msgstr "**可选的 ``proxy`` 字段(仅 ``json_api`` 支持)。**"
#: ../../source/settings.rst:177 0e0bd3b653784dd49f95cb942fca57f4
#: ../../source/settings.rst:213 08bf49a34630456db598e3e585a3e128
msgid ""
"A module may carry a ``proxy`` entry that the solver routes the upstream "
"request through. Useful when a site enforces ``ip_reputation`` rules that"
" block the solver host. Two forms are accepted:"
msgstr ""
"每个模块都可以带一个 ``proxy`` 字段 —— 求解器会通过该代理转发上游请求。"
"在站点启用了会封锁求解器主机的 ``ip_reputation`` 规则时,这会非常有用。"
"接受两种写法:"
"每个模块都可以带一个 ``proxy`` 字段 —— 求解器会通过该代理转发上游请求。在站点启用了会封锁求解器主机的 "
"``ip_reputation`` 规则时,这会非常有用。接受两种写法:"
#: ../../source/settings.rst:191 9720e46d246347faa4ccd5cbab26b12c
#: ../../source/settings.rst:227 7e0856096ecb44599b40a1e0efbb7fbb
msgid ""
"Only ``url``/``username``/``password`` are forwarded; other keys are "
"dropped. Cloudflare ``Error 1015 / 1020`` responses indicate the IP is "
"rate-limited or banned — switch the proxy rather than retrying. .. _ai-"
"analysis-settings:"
msgstr ""
"仅 ``url``/``username``/``password`` 会被转发;其它字段会被丢弃。Cloudflare "
"``Error 1015 / 1020`` 响应表示该 IP 被限速或被封 —— 此时请更换代理,而不是"
"反复重试。 .. _ai-analysis-settings:"
"仅 ``url``/``username``/``password`` 会被转发;其它字段会被丢弃。Cloudflare ``Error 1015"
" / 1020`` 响应表示该 IP 被限速或被封 —— 此时请更换代理,而不是反复重试。 .. _ai-analysis-settings:"
#: ../../source/settings.rst:197 5289b3aac94445e59bab01015a6c4c21
#: ../../source/settings.rst:233 c0352f79365140edadb45dfe6e0373d3
msgid "AI analysis"
msgstr "AI 分析"
#: ../../source/settings.rst:199 da442ac518a047c390afff9ddb1e4f01
#: ../../source/settings.rst:235 bf3d82f2b15745cb8a1b4dfed7c9f836
msgid ""
"The ``--ai`` flag (see :ref:`ai-analysis`) talks to an OpenAI-compatible "
"chat completion API. Three settings control how that request is made:"
msgstr ""
"``--ai`` 参数(参见 :ref:`ai-analysis`)会调用一个 OpenAI 兼容的 chat "
"completion 接口。以下三个配置项决定该请求的具体行为:"
"``--ai`` 参数(参见 :ref:`ai-analysis`)会调用一个 OpenAI 兼容的 chat completion "
"接口。以下三个配置项决定该请求的具体行为:"
#: ../../source/settings.rst:209 4fb53837481444ee8d74ecb2a793363b
#: ../../source/settings.rst:245 5fbd903f98e64b349c146792cc7ab2e9
msgid "``openai_api_key``"
msgstr "``openai_api_key``"
#: ../../source/settings.rst:210 4c5a241e1ac848819390ba0845e3fb7a
#: ../../source/settings.rst:246 c73824b01b8e4cb8aabfed01c94ea2ad
msgid "``\"\"`` (empty)"
msgstr "``\"\"``\ (空)"
msgstr "``\"\"``\\ (空)"
#: ../../source/settings.rst:211 6994e781bc5e4988a804a239cc20630e
#: ../../source/settings.rst:247 82aaaef9d7cc4665813cdd874130bdb7
msgid ""
"API key. If empty, Maigret falls back to the ``OPENAI_API_KEY`` "
"environment variable."
msgstr ""
"API key。为空时,Maigret 会回退到 ``OPENAI_API_KEY`` 环境变量。"
msgstr "API key。为空时,Maigret 会回退到 ``OPENAI_API_KEY`` 环境变量。"
#: ../../source/settings.rst:213 ae8fc24725884c4cbe99db369c197682
#: ../../source/settings.rst:249 037412797a4c42519aef357c77d1833f
msgid "``openai_model``"
msgstr "``openai_model``"
#: ../../source/settings.rst:214 a685b4608f0b4e6dbdfafd7445732916
#: ../../source/settings.rst:250 2562a1def3be41889c3b05620eb1870b
msgid "``gpt-4o``"
msgstr "``gpt-4o``"
#: ../../source/settings.rst:215 bc3d800a38de4978811fee2bf3ced6f6
#: ../../source/settings.rst:251 0d3623bf37a84a0399c893f90dae649a
msgid "Default model name. Overridable per-run with ``--ai-model``."
msgstr "默认模型名。可在单次运行中通过 ``--ai-model`` 覆盖。"
#: ../../source/settings.rst:216 c12beb71258348c7bb3e1e35d701d48a
#: ../../source/settings.rst:252 f6ae5711a47f42e4a6effae3c90c2560
msgid "``openai_api_base_url``"
msgstr "``openai_api_base_url``"
#: ../../source/settings.rst:217 13d8d8a7bd3a47bdbdaaeaf2b9f6de35
#: ../../source/settings.rst:253 4aac62c2d35148328d255646e18623d4
msgid "``https://api.openai.com/v1``"
msgstr "``https://api.openai.com/v1``"
#: ../../source/settings.rst:218 c4ed64bb43504c85bebd71ecc77f11a3
#: ../../source/settings.rst:254 6096b4d81ac248a09f6f49f5d8303676
msgid ""
"Base URL of the chat completion API. Point this at any OpenAI-compatible "
"service (Azure OpenAI, OpenRouter, a local server, …) to use it instead "
@@ -401,23 +410,33 @@ msgstr ""
"chat completion 接口的基础 URL。把它指向任何 OpenAI 兼容的服务(Azure "
"OpenAI、OpenRouter、本地推理服务等),即可用其代替 OpenAI 官方服务。"
#: ../../source/settings.rst:222 edc77536812e4e1e9dce3a93f8b41699
#: ../../source/settings.rst:258 186158107d2b4ee1af1a46a7e45f6c1a
msgid "Example ``~/.maigret/settings.json`` snippet using a non-OpenAI endpoint:"
msgstr "下面是一个使用非 OpenAI 接口的 ``~/.maigret/settings.json`` 片段示例:"
#: ../../source/settings.rst:233 c518d020066741ce9af7f0a12b4e7815
#: ../../source/settings.rst:269 2e37565d7dd74e9898cacf648c27476a
msgid ""
"The key resolution order is ``settings.openai_api_key`` → "
"``OPENAI_API_KEY`` environment variable; the first non-empty value wins."
msgstr ""
"API key 的取值顺序为:``settings.openai_api_key`` → ``OPENAI_API_KEY`` 环境"
"变量;以第一个非空值为准。"
"API key 的取值顺序为:``settings.openai_api_key`` → ``OPENAI_API_KEY`` "
"环境变量;以第一个非空值为准。"
#: ../../source/settings.rst:238 d75ced8c84484711b4db002a082d5c8e
#: ../../source/settings.rst:274 0bb83aab896446628c567ec9e33644a1
msgid ""
"``--ai`` sends the full internal Markdown report (which contains the "
"gathered profile data) to the configured endpoint. Only use providers and"
" accounts you trust with that data."
msgstr ""
"``--ai`` 会把完整的内部 Markdown 报告(其中包含收集到的所有个人主页数据)"
"发送至所配置的接口。请仅在你信任的服务商和账号上使用该功能。"
"``--ai`` 会把完整的内部 Markdown "
"报告(其中包含收集到的所有个人主页数据)发送至所配置的接口。请仅在你信任的服务商和账号上使用该功能。"
#~ msgid ""
#~ "The ``cloudflare_bypass`` block in "
#~ "``settings.json`` configures the optional "
#~ "bypass described in :ref:`cloudflare-bypass`."
#~ " Default value:"
#~ msgstr ""
#~ "``settings.json`` 中的 ``cloudflare_bypass`` 配置块用于配置"
#~ " :ref:`cloudflare-bypass` 所述的可选绕过机制。默认值如下:"
+37 -1
View File
@@ -112,7 +112,43 @@ Cloudflare webgate
rules may change without backwards-compatibility guarantees.
The ``cloudflare_bypass`` block in ``settings.json`` configures the optional
bypass described in :ref:`cloudflare-bypass`. Default value:
bypass described in :ref:`cloudflare-bypass`. The same block is honoured by
the CLI, the Python API, and the web UI (``python -m maigret.web.app``); set
``enabled: true`` once and every entry point routes cf-protected sites
through the solver.
**Minimal FlareSolverr setup.** Start the solver in Docker, then drop the
following snippet into ``~/.maigret/settings.json`` (or any path listed in
:ref:`settings`):
.. code-block:: bash
docker run -d -p 8191:8191 --name flaresolverr \
ghcr.io/flaresolverr/flaresolverr:latest
.. code-block:: json
{
"cloudflare_bypass": {
"enabled": true,
"modules": [
{
"name": "flaresolverr",
"method": "json_api",
"url": "http://localhost:8191/v1",
"max_timeout_ms": 60000
}
]
}
}
That is enough — ``session_prefix`` and ``trigger_protection`` fall back to
sensible defaults (``"maigret"`` and
``["cf_js_challenge", "cf_firewall", "webgate"]`` respectively). On the next
run, Maigret logs ``Cloudflare webgate active: ...`` and routes matching
sites through the solver.
Default value (full schema with every supported field):
.. code-block:: json
+15
View File
@@ -17,6 +17,7 @@ from threading import Thread
from typing import Any, Dict
import maigret
import maigret.settings
from maigret.checking import build_cloudflare_bypass_config
from maigret.sites import MaigretDatabase
from maigret.report import generate_report_context
@@ -44,6 +45,19 @@ def setup_logger(log_level, name):
async def maigret_search(username, options):
logger = setup_logger(logging.WARNING, 'maigret')
try:
settings = maigret.settings.Settings()
settings.load()
cf_bypass_config = build_cloudflare_bypass_config(settings)
if cf_bypass_config:
modules_summary = ", ".join(
f"{m.get('name', m.get('method'))}({m.get('url')})"
for m in cf_bypass_config["modules"]
)
logger.info(
f"Cloudflare webgate active: triggers={cf_bypass_config['trigger_protection']}, "
f"modules=[{modules_summary}]"
)
db = MaigretDatabase().load_from_path(app.config["MAIGRET_DB_FILE"])
top_sites = int(options.get('top_sites') or 500)
@@ -81,6 +95,7 @@ async def maigret_search(username, options):
proxy=options.get('proxy', None),
tor_proxy=options.get('tor_proxy', None),
i2p_proxy=options.get('i2p_proxy', None),
cloudflare_bypass=cf_bypass_config,
)
return results
except Exception as e:
+81
View File
@@ -12,6 +12,7 @@ import pytest
import maigret
import maigret.report
import maigret.settings
from maigret.web import app as web_app_module
@@ -189,6 +190,86 @@ def test_download_report_blocks_absolute_path(client, web_app, tmp_path):
assert b'ABSOLUTE' not in resp.get_data()
def test_search_passes_cloudflare_bypass_from_settings(client, web_app, monkeypatch):
"""If settings.json enables cloudflare_bypass with a valid FlareSolverr module,
the web search must forward that config to maigret.search via the
cloudflare_bypass kwarg. Guards the wiring in maigret_search()."""
captured = {}
async def fake_search(*args, **kwargs):
captured.update(kwargs)
return {}
def fake_load(self, paths=None):
self.cloudflare_bypass = {
"enabled": True,
"session_prefix": "test-prefix",
"trigger_protection": ["cf_js_challenge"],
"modules": [
{
"name": "flaresolverr",
"method": "json_api",
"url": "http://flare.test:8191/v1",
"max_timeout_ms": 60000,
}
],
}
return True, ""
monkeypatch.setattr(maigret.settings.Settings, 'load', fake_load)
monkeypatch.setattr(maigret, 'search', fake_search)
monkeypatch.setattr(maigret.report, 'save_graph_report', lambda *a, **kw: None)
monkeypatch.setattr(maigret.report, 'save_csv_report', lambda *a, **kw: None)
monkeypatch.setattr(maigret.report, 'save_json_report', lambda *a, **kw: None)
monkeypatch.setattr(maigret.report, 'save_pdf_report', lambda *a, **kw: None)
monkeypatch.setattr(maigret.report, 'save_html_report', lambda *a, **kw: None)
monkeypatch.setattr(maigret.report, 'generate_report_context', lambda *a, **kw: {})
monkeypatch.setattr(web_app, 'Thread', _SyncThread)
client.post('/search', data={'usernames': 'testuser'})
assert 'cloudflare_bypass' in captured, (
'maigret.search was not given a cloudflare_bypass kwarg'
)
cf = captured['cloudflare_bypass']
assert cf is not None
assert cf['session_prefix'] == 'test-prefix'
assert cf['trigger_protection'] == ['cf_js_challenge']
assert len(cf['modules']) == 1
assert cf['modules'][0]['url'] == 'http://flare.test:8191/v1'
assert cf['modules'][0]['method'] == 'json_api'
def test_search_omits_cloudflare_bypass_when_disabled(client, web_app, monkeypatch):
"""When settings has no cloudflare_bypass (or enabled=false), the kwarg
must be None so the default checker pipeline runs."""
captured = {}
async def fake_search(*args, **kwargs):
captured.update(kwargs)
return {}
def fake_load(self, paths=None):
# no cloudflare_bypass attribute at all
return True, ""
monkeypatch.setattr(maigret.settings.Settings, 'load', fake_load)
monkeypatch.setattr(maigret, 'search', fake_search)
monkeypatch.setattr(maigret.report, 'save_graph_report', lambda *a, **kw: None)
monkeypatch.setattr(maigret.report, 'save_csv_report', lambda *a, **kw: None)
monkeypatch.setattr(maigret.report, 'save_json_report', lambda *a, **kw: None)
monkeypatch.setattr(maigret.report, 'save_pdf_report', lambda *a, **kw: None)
monkeypatch.setattr(maigret.report, 'save_html_report', lambda *a, **kw: None)
monkeypatch.setattr(maigret.report, 'generate_report_context', lambda *a, **kw: {})
monkeypatch.setattr(web_app, 'Thread', _SyncThread)
client.post('/search', data={'usernames': 'testuser'})
assert captured.get('cloudflare_bypass') is None
def test_real_report_generation_does_not_crash(client, web_app, monkeypatch):
"""End-to-end with mocked maigret.search but REAL report generation.