tgcaptcha-solver 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- tgcaptcha_solver-0.1.0/LICENSE +21 -0
- tgcaptcha_solver-0.1.0/PKG-INFO +387 -0
- tgcaptcha_solver-0.1.0/README.md +324 -0
- tgcaptcha_solver-0.1.0/pyproject.toml +49 -0
- tgcaptcha_solver-0.1.0/setup.cfg +4 -0
- tgcaptcha_solver-0.1.0/tgcaptcha/__init__.py +29 -0
- tgcaptcha_solver-0.1.0/tgcaptcha/adapters/__init__.py +25 -0
- tgcaptcha_solver-0.1.0/tgcaptcha/adapters/pyrogram.py +508 -0
- tgcaptcha_solver-0.1.0/tgcaptcha/adapters/tdlib.py +684 -0
- tgcaptcha_solver-0.1.0/tgcaptcha/client.py +87 -0
- tgcaptcha_solver-0.1.0/tgcaptcha/engine.py +122 -0
- tgcaptcha_solver-0.1.0/tgcaptcha/executor.py +453 -0
- tgcaptcha_solver-0.1.0/tgcaptcha/hands.py +123 -0
- tgcaptcha_solver-0.1.0/tgcaptcha/model.py +245 -0
- tgcaptcha_solver-0.1.0/tgcaptcha/policy.py +254 -0
- tgcaptcha_solver-0.1.0/tgcaptcha/replay.py +156 -0
- tgcaptcha_solver-0.1.0/tgcaptcha/rules.py +184 -0
- tgcaptcha_solver-0.1.0/tgcaptcha/runner.py +312 -0
- tgcaptcha_solver-0.1.0/tgcaptcha/server.py +188 -0
- tgcaptcha_solver-0.1.0/tgcaptcha/solvers/__init__.py +50 -0
- tgcaptcha_solver-0.1.0/tgcaptcha/solvers/bio.py +180 -0
- tgcaptcha_solver-0.1.0/tgcaptcha/solvers/builtin.py +162 -0
- tgcaptcha_solver-0.1.0/tgcaptcha/solvers/dm.py +171 -0
- tgcaptcha_solver-0.1.0/tgcaptcha/solvers/emoji.py +119 -0
- tgcaptcha_solver-0.1.0/tgcaptcha/solvers/gates.py +287 -0
- tgcaptcha_solver-0.1.0/tgcaptcha/solvers/image.py +267 -0
- tgcaptcha_solver-0.1.0/tgcaptcha/solvers/image_digits.py +216 -0
- tgcaptcha_solver-0.1.0/tgcaptcha/solvers/image_text_pick.py +379 -0
- tgcaptcha_solver-0.1.0/tgcaptcha/solvers/ocr.py +153 -0
- tgcaptcha_solver-0.1.0/tgcaptcha/solvers/qa.py +127 -0
- tgcaptcha_solver-0.1.0/tgcaptcha/solvers/rose.py +334 -0
- tgcaptcha_solver-0.1.0/tgcaptcha/solvers/success.py +70 -0
- tgcaptcha_solver-0.1.0/tgcaptcha/solvers/video.py +204 -0
- tgcaptcha_solver-0.1.0/tgcaptcha/tests/__init__.py +0 -0
- tgcaptcha_solver-0.1.0/tgcaptcha/tests/test_bio.py +431 -0
- tgcaptcha_solver-0.1.0/tgcaptcha/tests/test_core.py +961 -0
- tgcaptcha_solver-0.1.0/tgcaptcha/tests/test_image_digits.py +263 -0
- tgcaptcha_solver-0.1.0/tgcaptcha/tests/test_image_pick.py +353 -0
- tgcaptcha_solver-0.1.0/tgcaptcha/tests/test_pyro_adapter.py +498 -0
- tgcaptcha_solver-0.1.0/tgcaptcha/tests/test_runner.py +187 -0
- tgcaptcha_solver-0.1.0/tgcaptcha/tests/test_success.py +117 -0
- tgcaptcha_solver-0.1.0/tgcaptcha/tests/test_tdlib_adapter.py +737 -0
- tgcaptcha_solver-0.1.0/tgcaptcha/tests/test_video.py +127 -0
- tgcaptcha_solver-0.1.0/tgcaptcha/text.py +398 -0
- tgcaptcha_solver-0.1.0/tgcaptcha_solver.egg-info/PKG-INFO +387 -0
- tgcaptcha_solver-0.1.0/tgcaptcha_solver.egg-info/SOURCES.txt +47 -0
- tgcaptcha_solver-0.1.0/tgcaptcha_solver.egg-info/dependency_links.txt +1 -0
- tgcaptcha_solver-0.1.0/tgcaptcha_solver.egg-info/requires.txt +47 -0
- tgcaptcha_solver-0.1.0/tgcaptcha_solver.egg-info/top_level.txt +1 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 drshta0
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,387 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: tgcaptcha-solver
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Telegram captcha solver for Rose, GroupHelp, Shieldy and SOSO group-join bots, with a strict safety policy.
|
|
5
|
+
Author: drshta0
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/drshta0/tgcaptcha-solver
|
|
8
|
+
Project-URL: Repository, https://github.com/drshta0/tgcaptcha-solver
|
|
9
|
+
Project-URL: Issues, https://github.com/drshta0/tgcaptcha-solver/issues
|
|
10
|
+
Project-URL: Changelog, https://github.com/drshta0/tgcaptcha-solver/blob/main/CHANGELOG.md
|
|
11
|
+
Project-URL: Documentation, https://github.com/drshta0/tgcaptcha-solver/blob/main/docs/USAGE.md
|
|
12
|
+
Keywords: telegram,captcha,captcha-solver,telegram-captcha,telethon,userbot,missrose,rose-bot,grouphelp,shieldy,ocr,automation
|
|
13
|
+
Classifier: Development Status :: 4 - Beta
|
|
14
|
+
Classifier: Intended Audience :: Developers
|
|
15
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
16
|
+
Classifier: Operating System :: OS Independent
|
|
17
|
+
Classifier: Programming Language :: Python :: 3
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
21
|
+
Classifier: Topic :: Communications :: Chat
|
|
22
|
+
Requires-Python: >=3.10
|
|
23
|
+
Description-Content-Type: text/markdown
|
|
24
|
+
License-File: LICENSE
|
|
25
|
+
Provides-Extra: client
|
|
26
|
+
Requires-Dist: aiohttp>=3.9; extra == "client"
|
|
27
|
+
Provides-Extra: executor
|
|
28
|
+
Requires-Dist: telethon>=1.36; extra == "executor"
|
|
29
|
+
Requires-Dist: aiohttp>=3.9; extra == "executor"
|
|
30
|
+
Provides-Extra: kurigram
|
|
31
|
+
Requires-Dist: kurigram>=2.0; extra == "kurigram"
|
|
32
|
+
Requires-Dist: aiohttp>=3.9; extra == "kurigram"
|
|
33
|
+
Provides-Extra: telethon
|
|
34
|
+
Requires-Dist: telethon>=1.36; extra == "telethon"
|
|
35
|
+
Requires-Dist: aiohttp>=3.9; extra == "telethon"
|
|
36
|
+
Provides-Extra: hydrogram
|
|
37
|
+
Requires-Dist: hydrogram>=0.2; extra == "hydrogram"
|
|
38
|
+
Requires-Dist: aiohttp>=3.9; extra == "hydrogram"
|
|
39
|
+
Provides-Extra: tdlib
|
|
40
|
+
Requires-Dist: aiotdlib<0.28,>=0.27.6; extra == "tdlib"
|
|
41
|
+
Requires-Dist: aiohttp>=3.9; extra == "tdlib"
|
|
42
|
+
Provides-Extra: server
|
|
43
|
+
Requires-Dist: fastapi>=0.110; extra == "server"
|
|
44
|
+
Requires-Dist: uvicorn>=0.29; extra == "server"
|
|
45
|
+
Requires-Dist: PyYAML>=6.0; extra == "server"
|
|
46
|
+
Requires-Dist: Pillow>=10.0; extra == "server"
|
|
47
|
+
Provides-Extra: ocr
|
|
48
|
+
Requires-Dist: ddddocr>=1.4; extra == "ocr"
|
|
49
|
+
Provides-Extra: test
|
|
50
|
+
Requires-Dist: aiohttp>=3.9; extra == "test"
|
|
51
|
+
Requires-Dist: fastapi>=0.110; extra == "test"
|
|
52
|
+
Requires-Dist: uvicorn>=0.29; extra == "test"
|
|
53
|
+
Requires-Dist: PyYAML>=6.0; extra == "test"
|
|
54
|
+
Requires-Dist: Pillow>=10.0; extra == "test"
|
|
55
|
+
Provides-Extra: all
|
|
56
|
+
Requires-Dist: aiohttp>=3.9; extra == "all"
|
|
57
|
+
Requires-Dist: telethon>=1.36; extra == "all"
|
|
58
|
+
Requires-Dist: fastapi>=0.110; extra == "all"
|
|
59
|
+
Requires-Dist: uvicorn>=0.29; extra == "all"
|
|
60
|
+
Requires-Dist: PyYAML>=6.0; extra == "all"
|
|
61
|
+
Requires-Dist: Pillow>=10.0; extra == "all"
|
|
62
|
+
Dynamic: license-file
|
|
63
|
+
|
|
64
|
+
<p align="center">
|
|
65
|
+
<img src="https://raw.githubusercontent.com/drshta0/tgcaptcha-solver/main/docs/media/banner.svg" width="100%" alt="tgcaptcha: open-source Telegram captcha solver for Rose, GroupHelp, Shieldy and SOSO" />
|
|
66
|
+
</p>
|
|
67
|
+
|
|
68
|
+
<p align="center">
|
|
69
|
+
<a href="#install"><img src="https://img.shields.io/badge/python-3.10%2B-2aabee?style=flat-square" alt="Python 3.10+" /></a>
|
|
70
|
+
<a href="#install"><img src="https://img.shields.io/badge/core%20deps-0-3fb950?style=flat-square" alt="Zero core dependencies" /></a>
|
|
71
|
+
<a href="#tests"><img src="https://img.shields.io/badge/tests-384%20offline-3fb950?style=flat-square" alt="384 offline checks" /></a>
|
|
72
|
+
<a href="https://github.com/drshta0/tgcaptcha-solver/blob/main/LICENSE"><img src="https://img.shields.io/badge/license-MIT-8b949e?style=flat-square" alt="MIT" /></a>
|
|
73
|
+
</p>
|
|
74
|
+
|
|
75
|
+
<p align="center">
|
|
76
|
+
<a href="#install">Install</a> ·
|
|
77
|
+
<a href="#quickstart">Quickstart</a> ·
|
|
78
|
+
<a href="#works-with">Works with</a> ·
|
|
79
|
+
<a href="#all-solvers">Solvers</a> ·
|
|
80
|
+
<a href="#safety">Safety</a> ·
|
|
81
|
+
<a href="https://github.com/drshta0/tgcaptcha-solver/blob/main/docs/USAGE.md">Docs</a> ·
|
|
82
|
+
<a href="https://github.com/drshta0/tgcaptcha-solver/blob/main/CONTRIBUTING.md">Contributing</a>
|
|
83
|
+
</p>
|
|
84
|
+
|
|
85
|
+
<br />
|
|
86
|
+
|
|
87
|
+
**tgcaptcha** is an open-source Telegram captcha solver. When your account
|
|
88
|
+
joins a group, bots like **Rose**, **GroupHelp**, **Shieldy** and **SOSO 守门**
|
|
89
|
+
post a captcha: press a button, solve a sum, read a picture. tgcaptcha reads
|
|
90
|
+
it, works out the answer, checks the action against a strict safety policy,
|
|
91
|
+
and replies after a human-length pause. It runs on any Telegram client
|
|
92
|
+
framework: adapters ship for Telethon, the Pyrogram family (pyrogram,
|
|
93
|
+
kurigram, pyrofork, hydrogram) and TDLib hosts via aiotdlib, and any
|
|
94
|
+
other framework needs about 60 lines — see
|
|
95
|
+
[docs/ADAPTERS.md](https://github.com/drshta0/tgcaptcha-solver/blob/main/docs/ADAPTERS.md).
|
|
96
|
+
|
|
97
|
+
<p align="center">
|
|
98
|
+
<img src="https://raw.githubusercontent.com/drshta0/tgcaptcha-solver/main/docs/media/demo.svg" width="100%" alt="Animated demo: tgcaptcha solves GroupHelp, SOSO and Rose captchas, then refuses to click a scam wallet gate" />
|
|
99
|
+
</p>
|
|
100
|
+
|
|
101
|
+
## Works with
|
|
102
|
+
|
|
103
|
+
Replayed against 30 days of real challenges from each bot. "Handled" counts
|
|
104
|
+
solved challenges plus Rose welcome walls that are correctly skipped.
|
|
105
|
+
|
|
106
|
+
| Bot | What it asks | Handled | Real-account test |
|
|
107
|
+
|:--|:--|--:|:--|
|
|
108
|
+
| **Rose** `@MissRose_bot` | sum, word or letters in a distorted image, sent in DM | **99.8%** of 4,456 | ✅ all captcha modes |
|
|
109
|
+
| **GroupHelp** `@GroupHelpBot` | press "I'm not a bot" / "Unmute me" | **94.8%** of 2,525 | ✅ 3 of 3 passed |
|
|
110
|
+
| **Shieldy** `@shieldy_bot` | type the answer to a sum, or digits from an image | **97.3%** of 2,019 | |
|
|
111
|
+
| **SOSO 守门** and relatives | pick the answer to `6 + 5 = ?` | **99.6%** of 1,808 | |
|
|
112
|
+
| **Bio guards** `@group_protection_pro_bot` | remove the link from your bio, press Recheck | **100%** of 1,863 | ✅ end to end |
|
|
113
|
+
| **GroupHelp clones** (ghclone2 to 5, im_grouphelp) | same as GroupHelp | 80 to 100% | |
|
|
114
|
+
| **Rose clones** (missrose2, rose_rosebot) | same as Rose | 97 to 99.5% | |
|
|
115
|
+
|
|
116
|
+
The busiest gate bots in the data (nnai8688, nmnmfun, coolestbot) are all
|
|
117
|
+
above 99.5%. New clones usually work without changes, because solvers match
|
|
118
|
+
the shape of a challenge rather than the bot's name.
|
|
119
|
+
|
|
120
|
+
## Results
|
|
121
|
+
|
|
122
|
+
Measured by replaying 30 days of real traffic (167,198 challenges from 1,502
|
|
123
|
+
gate bots) through the same engine that runs live. No network needed.
|
|
124
|
+
|
|
125
|
+
| Outcome | Share | Challenges | Notes |
|
|
126
|
+
|:--|--:|--:|:--|
|
|
127
|
+
| Solved | **86.9%** | 145,252 | 15 built-in solvers |
|
|
128
|
+
| Ignored on purpose | 9.5% | 15,847 | scam buttons and welcome walls, never clicked |
|
|
129
|
+
| Unsolved | 3.6% | 6,099 | video or sticker captchas, images that were never captured |
|
|
130
|
+
|
|
131
|
+
Answer timing matters. A correct answer about 2 s after the challenge still got
|
|
132
|
+
accounts kicked. Waiting 8 to 22 s turned most of those kicks into passes.
|
|
133
|
+
|
|
134
|
+
## Install
|
|
135
|
+
|
|
136
|
+
Python 3.10 or newer. The distribution is `tgcaptcha-solver`; the import is
|
|
137
|
+
still `tgcaptcha`. The core (engine, rules, solvers, policy, replay) uses only
|
|
138
|
+
the standard library. Each side installs its own extras:
|
|
139
|
+
|
|
140
|
+
```bash
|
|
141
|
+
pip install -e ".[kurigram]" # Pyrogram-family accounts (kurigram / pyrofork)
|
|
142
|
+
pip install -e ".[hydrogram]" # hydrogram accounts (auto-detected family)
|
|
143
|
+
pip install -e ".[tdlib]" # TDLib hosts via aiotdlib (Linux/macOS-arm wheels)
|
|
144
|
+
pip install -e ".[telethon]" # Telethon accounts
|
|
145
|
+
pip install -e ".[server]" # solver service: fastapi, uvicorn, yaml, pillow
|
|
146
|
+
pip install -e ".[client]" # talk to the service from the account host: aiohttp
|
|
147
|
+
pip install -e ".[executor]" # Telethon-side executor: telethon, aiohttp
|
|
148
|
+
pip install ddddocr # optional OCR for the image solvers
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
`image_buttons` uses the `tesseract` binary. `rose_dm`, `image_text_pick` and
|
|
152
|
+
`image_digits_typed` use `ddddocr`. A solver skips itself when its OCR reader
|
|
153
|
+
is missing, so both are optional.
|
|
154
|
+
|
|
155
|
+
## 60-second setup (one account, no server)
|
|
156
|
+
|
|
157
|
+
The engine runs locally on your own machine — nothing to host, no token, no
|
|
158
|
+
config file. Mount it on your client and it watches every group you are in
|
|
159
|
+
for a captcha challenge that names you, solves it, and touches nothing else.
|
|
160
|
+
|
|
161
|
+
**Pyrogram family** (pyrogram, kurigram, pyrofork, hydrogram):
|
|
162
|
+
|
|
163
|
+
```python
|
|
164
|
+
from pyrogram import Client
|
|
165
|
+
from tgcaptcha.adapters import mount
|
|
166
|
+
|
|
167
|
+
app = Client("myaccount")
|
|
168
|
+
mount(app)
|
|
169
|
+
app.run()
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
**Telethon:**
|
|
173
|
+
|
|
174
|
+
```python
|
|
175
|
+
from telethon import TelegramClient
|
|
176
|
+
from tgcaptcha.executor import mount_telethon
|
|
177
|
+
|
|
178
|
+
client = TelegramClient("myaccount", api_id, api_hash)
|
|
179
|
+
mount_telethon(client)
|
|
180
|
+
await client.start()
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
**TDLib (aiotdlib):**
|
|
184
|
+
|
|
185
|
+
```python
|
|
186
|
+
from aiotdlib import Client
|
|
187
|
+
from tgcaptcha.adapters.tdlib import mount as mount_tdlib
|
|
188
|
+
|
|
189
|
+
client = Client(api_id, api_hash, database_encryption_key="...")
|
|
190
|
+
mount_tdlib(client)
|
|
191
|
+
await client.idle()
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
Linux and macOS-arm64 wheels bundle libtdjson (nothing to compile);
|
|
195
|
+
elsewhere TDLib must be built first. Upstream aiotdlib is frozen at
|
|
196
|
+
TDLib 1.8.46 — see [docs/ADAPTERS.md](https://github.com/drshta0/tgcaptcha-solver/blob/main/docs/ADAPTERS.md) for the
|
|
197
|
+
caveats, including the URL-button lane degradation.
|
|
198
|
+
|
|
199
|
+
**Any other framework:** implement nine async methods (click, send text,
|
|
200
|
+
send a sticker, fetch an image, read/write your bio, open a bot DM, join
|
|
201
|
+
a channel, set a last name) and feed them to the shared loop — template in
|
|
202
|
+
[`examples/diy_adapter.py`](https://github.com/drshta0/tgcaptcha-solver/blob/main/examples/diy_adapter.py), contract in
|
|
203
|
+
[docs/ADAPTERS.md](https://github.com/drshta0/tgcaptcha-solver/blob/main/docs/ADAPTERS.md). The safety policy runs inside the
|
|
204
|
+
loop on every action, so no adapter can click a trap button.
|
|
205
|
+
|
|
206
|
+
**Node.js (gramjs):** the same loop, policy and wire model ship as
|
|
207
|
+
TypeScript in [`node/`](https://github.com/drshta0/tgcaptcha-solver/blob/main/node/) — `npm i` there, then
|
|
208
|
+
`mount(client)` from `tgcaptcha-node`. The brain talks to your solver
|
|
209
|
+
service over the same `/v1/decide` protocol; the safety policy runs
|
|
210
|
+
in-process on the Node host, exactly as in Python. Parity with the
|
|
211
|
+
Python engine is pinned by golden vectors (1,888 policy verdicts, 12
|
|
212
|
+
runner transcripts, zero diffs) — see [`node/README.md`](https://github.com/drshta0/tgcaptcha-solver/blob/main/node/README.md).
|
|
213
|
+
|
|
214
|
+
Optional: pass `delay_fn` for a human-length pause before answering
|
|
215
|
+
(answering in ~2 s gets correct answers kicked), or host callbacks for
|
|
216
|
+
joins and last-name edits. Running several accounts is when the
|
|
217
|
+
optional solver service starts to pay off — see below.
|
|
218
|
+
|
|
219
|
+
## Quickstart
|
|
220
|
+
|
|
221
|
+
```python
|
|
222
|
+
from tgcaptcha import Account, Button, Engine, Message, Session
|
|
223
|
+
|
|
224
|
+
s = Session(
|
|
225
|
+
session_id="demo",
|
|
226
|
+
account=Account(123, "me", first_name="Alex"),
|
|
227
|
+
challenge=Message(
|
|
228
|
+
msg_id=1,
|
|
229
|
+
text="Alex, **press the button** below within 1 Minute 👇🏻",
|
|
230
|
+
buttons=[[Button("CLICK 👉🏻 I'm NOT a BOT 🤖")]],
|
|
231
|
+
sender_id=42, sender_username="grouphelpbot",
|
|
232
|
+
),
|
|
233
|
+
chat_title="Some Group",
|
|
234
|
+
names_account=True, # the challenge mentions this account
|
|
235
|
+
)
|
|
236
|
+
|
|
237
|
+
d = Engine().decide(s)
|
|
238
|
+
print(d.solver) # verify_button
|
|
239
|
+
print(d.actions) # [Click(label="CLICK 👉🏻 I'm NOT a BOT 🤖")]
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
That runs locally with no service and no config. The full setup (service,
|
|
243
|
+
executor, Telethon) is in [docs/USAGE.md](https://github.com/drshta0/tgcaptcha-solver/blob/main/docs/USAGE.md).
|
|
244
|
+
|
|
245
|
+
## All solvers
|
|
246
|
+
|
|
247
|
+
| Solver | Gate bots | Challenge | Tested |
|
|
248
|
+
|:--|:--|:--|:--|
|
|
249
|
+
| `math_buttons` | SOSO 守门 and relatives (64% of traffic), nmnmfun | `6 + 5 = ?` with answer buttons | unit, replay |
|
|
250
|
+
| `verify_button` | GroupHelp and 5 clones, Shieldy, long tail | one "I'm not a bot" button, 10 languages | unit, replay, live |
|
|
251
|
+
| `math_typed` | Shieldy, filesreply | `(10 + 1)`, type the answer | unit, replay, live |
|
|
252
|
+
| `rose_dm` | MissRose | image or text challenge in DM, OCR | unit, replay, live |
|
|
253
|
+
| `image_text_pick` | clean3robot family | sum in an image, pick the matching button | unit, live |
|
|
254
|
+
| `image_digits_typed` | MissRose typed, long tail | digits in an image, type them | unit, replay |
|
|
255
|
+
| `image_buttons` | misc image gates | image plus buttons (tesseract) | unit, replay |
|
|
256
|
+
| `bio_guard` | @group_protection_pro_bot | link in bio: clear, Recheck, restore | unit, replay, live |
|
|
257
|
+
| `profile_requirement` | profile-gate bots | set a last name, then unmute | unit, replay |
|
|
258
|
+
| `join_required` | join-gate bots | join the named channel, then verify | unit, replay |
|
|
259
|
+
| `qa_buttons` | Customize_Captcha_Bot, quiz gates | fixed question, pick the answer | unit, replay |
|
|
260
|
+
| `emoji_pick` | emigrants360 and similar | "click the button with 🍏" | unit, replay |
|
|
261
|
+
| `say_anything` | "write any message" gates | send a short plain message | unit, replay |
|
|
262
|
+
| `dm_flow` | deep-link verifiers | follow the link into the bot's DM | unit, replay |
|
|
263
|
+
| `rose_welcome_wall` | MissRose | welcome walls, ignored on purpose | unit, replay |
|
|
264
|
+
|
|
265
|
+
Each file in `tgcaptcha/solvers/` lists the gate bots it was built from.
|
|
266
|
+
|
|
267
|
+
## Safety
|
|
268
|
+
|
|
269
|
+
Every action a solver proposes goes through the policy on the account's own
|
|
270
|
+
machine before anything happens. No solver is trusted, local or remote.
|
|
271
|
+
|
|
272
|
+
- **No trap buttons.** Kick, ban, casino and wallet labels are blocked, and that
|
|
273
|
+
check runs before any allow rule.
|
|
274
|
+
- **Only its own challenge.** It answers only challenges that mention this account.
|
|
275
|
+
- **Short plain text only.** No links, no mentions, no line breaks.
|
|
276
|
+
- **DMs only to the gate bot**, or to a bot the gate bot links to.
|
|
277
|
+
- **Joins only the channel the gate bot named.**
|
|
278
|
+
- **Profile edits only for bio-guard:** clear the bio once, then restore exactly
|
|
279
|
+
what was there.
|
|
280
|
+
- **Bounded.** Steps and actions are capped. After that it gives up.
|
|
281
|
+
|
|
282
|
+
## How it works
|
|
283
|
+
|
|
284
|
+
```
|
|
285
|
+
account host (Telethon) solver service
|
|
286
|
+
┌───────────────────────────────┐ session ┌──────────────────────┐
|
|
287
|
+
│ Executor observe, act │ ────────▶ │ Engine │
|
|
288
|
+
│ Policy checks each action │ ◀──────── │ rules (YAML) │
|
|
289
|
+
│ Engine local fallback │ decision │ solvers (plugins) │
|
|
290
|
+
└───────────────────────────────┘ └──────────────────────┘
|
|
291
|
+
```
|
|
292
|
+
|
|
293
|
+
- **Executor** (`executor.py`) turns a challenge into a `Session`, asks for a
|
|
294
|
+
`Decision`, runs each allowed action, then watches the gate bot for a few
|
|
295
|
+
seconds and repeats until done.
|
|
296
|
+
- **Policy** (`policy.py`) runs on the account's host and decides what is allowed.
|
|
297
|
+
- **Engine** (`engine.py`) tries rules first, then solvers, in order. It runs on
|
|
298
|
+
the service and also on the host as a fallback, so solving continues if the
|
|
299
|
+
service is down.
|
|
300
|
+
|
|
301
|
+
The executor can only do a fixed set of things (`model.py`): click, send text,
|
|
302
|
+
fetch image, fetch bio, open DM, join channel, set last name, set bio, wait,
|
|
303
|
+
done. New gate bots are handled by adding a rule or a solver.
|
|
304
|
+
|
|
305
|
+
## Adding a gate bot
|
|
306
|
+
|
|
307
|
+
Most bots need only a rule. The service reloads the rules file when it changes.
|
|
308
|
+
See [`rules.example.yaml`](https://github.com/drshta0/tgcaptcha-solver/blob/main/rules.example.yaml).
|
|
309
|
+
|
|
310
|
+
```yaml
|
|
311
|
+
- id: owlto-join
|
|
312
|
+
match: {bots: [Owlto_BOT]}
|
|
313
|
+
do: {click_label: "click\\s+to\\s+join"}
|
|
314
|
+
|
|
315
|
+
- id: filesreply
|
|
316
|
+
match: {bots: [filesreply_bot], text: "直接发送答案"}
|
|
317
|
+
do: {solver: math_typed}
|
|
318
|
+
|
|
319
|
+
- id: not-a-captcha
|
|
320
|
+
match: {bots: [fun_message_scoring_bot]}
|
|
321
|
+
do: {ignore: "quiz results"}
|
|
322
|
+
```
|
|
323
|
+
|
|
324
|
+
For harder cases (images, multi-step DM flows), write a solver: subclass
|
|
325
|
+
`tgcaptcha.solvers.Solver`, implement `decide(session)`, and put the file in the
|
|
326
|
+
service's `--plugins` folder (then `POST /v1/reload`). You can also publish it
|
|
327
|
+
under the `tgcaptcha.solvers` entry point. See
|
|
328
|
+
[`examples/custom_solver.py`](https://github.com/drshta0/tgcaptcha-solver/blob/main/examples/custom_solver.py).
|
|
329
|
+
|
|
330
|
+
## Testing a change on real traffic
|
|
331
|
+
|
|
332
|
+
```bash
|
|
333
|
+
python -m tgcaptcha.replay corpus.jsonl --rules new_rules.yaml --compare-to rules.yaml
|
|
334
|
+
```
|
|
335
|
+
|
|
336
|
+
This replays a stored corpus (JSON lines of sessions, or flat
|
|
337
|
+
`{bot, text, buttons, mode}` rows) and prints coverage per solver and per bot,
|
|
338
|
+
the most common challenges nothing answers, and every decision that changed
|
|
339
|
+
compared to the baseline. A change ships only if nothing that was solved
|
|
340
|
+
before stops being solved.
|
|
341
|
+
|
|
342
|
+
## Running the service
|
|
343
|
+
|
|
344
|
+
```bash
|
|
345
|
+
TGCAPTCHA_TOKEN=... python -m tgcaptcha.server --port 8090 \
|
|
346
|
+
--rules rules.yaml --plugins plugins/ --report reports.jsonl
|
|
347
|
+
```
|
|
348
|
+
|
|
349
|
+
Endpoints: `GET /v1/health`, `POST /v1/decide`, `POST /v1/report`,
|
|
350
|
+
`POST /v1/reload`, all behind a Bearer token. The service keeps no state; the
|
|
351
|
+
host sends the whole session on every step.
|
|
352
|
+
|
|
353
|
+
On the account's host:
|
|
354
|
+
|
|
355
|
+
```python
|
|
356
|
+
from tgcaptcha import Account
|
|
357
|
+
from tgcaptcha.client import Brain
|
|
358
|
+
from tgcaptcha.executor import Executor
|
|
359
|
+
|
|
360
|
+
brain = Brain("http://solver:8090", token="...") # Brain() runs locally only
|
|
361
|
+
ex = Executor(client, brain, account=Account(me.id, me.username),
|
|
362
|
+
delay_fn=lambda text: random.uniform(8, 22)) # human pause
|
|
363
|
+
result = await ex.run(chat, challenge_msg, names_account=True)
|
|
364
|
+
```
|
|
365
|
+
|
|
366
|
+
## Tests
|
|
367
|
+
|
|
368
|
+
```bash
|
|
369
|
+
python -m tgcaptcha.tests.test_core
|
|
370
|
+
python -m tgcaptcha.tests.test_bio
|
|
371
|
+
python -m tgcaptcha.tests.test_image_digits
|
|
372
|
+
python -m tgcaptcha.tests.test_image_pick
|
|
373
|
+
```
|
|
374
|
+
|
|
375
|
+
384 checks, all offline. CI runs them on Python 3.10 and 3.12, along with an
|
|
376
|
+
import check that keeps the package standalone.
|
|
377
|
+
|
|
378
|
+
## Responsible use
|
|
379
|
+
|
|
380
|
+
For education and research. Automating Telegram accounts may break Telegram's
|
|
381
|
+
Terms of Service, and you are responsible for your own accounts. Don't use it
|
|
382
|
+
to spam, scrape, or abuse any platform. The policy never clicks casino, wallet
|
|
383
|
+
or ad buttons, and that won't change.
|
|
384
|
+
|
|
385
|
+
## License
|
|
386
|
+
|
|
387
|
+
[MIT](https://github.com/drshta0/tgcaptcha-solver/blob/main/LICENSE)
|