cloud-phone-kit 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.
- cloud_phone_kit-0.1.0/.gitignore +15 -0
- cloud_phone_kit-0.1.0/CHANGELOG.md +9 -0
- cloud_phone_kit-0.1.0/LICENSE +21 -0
- cloud_phone_kit-0.1.0/PKG-INFO +128 -0
- cloud_phone_kit-0.1.0/README.md +95 -0
- cloud_phone_kit-0.1.0/cloud_phone_kit/__init__.py +3 -0
- cloud_phone_kit-0.1.0/cloud_phone_kit/cli.py +92 -0
- cloud_phone_kit-0.1.0/cloud_phone_kit/deal.py +25 -0
- cloud_phone_kit-0.1.0/cloud_phone_kit/proxy.py +49 -0
- cloud_phone_kit-0.1.0/cloud_phone_kit/readiness.py +91 -0
- cloud_phone_kit-0.1.0/docs/AFFILIATE.md +46 -0
- cloud_phone_kit-0.1.0/docs/FAQ.md +21 -0
- cloud_phone_kit-0.1.0/examples/phone.yaml +8 -0
- cloud_phone_kit-0.1.0/pyproject.toml +73 -0
- cloud_phone_kit-0.1.0/tests/test_cli.py +34 -0
- cloud_phone_kit-0.1.0/tests/test_proxy.py +22 -0
- cloud_phone_kit-0.1.0/tests/test_readiness.py +24 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 antidetect-importer contributors
|
|
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,128 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: cloud-phone-kit
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Multilogin Cloud Phone readiness — mobile proxy checks and TikTok/Instagram launch checklists. CLI: cloud-phone.
|
|
5
|
+
Project-URL: Homepage, https://pypi.org/project/cloud-phone-kit/
|
|
6
|
+
Project-URL: Documentation, https://pypi.org/project/cloud-phone-kit/
|
|
7
|
+
Project-URL: Repository, https://pypi.org/project/cloud-phone-kit/
|
|
8
|
+
Project-URL: Changelog, https://pypi.org/project/cloud-phone-kit/
|
|
9
|
+
Author: cloud-phone-kit contributors
|
|
10
|
+
License-Expression: MIT
|
|
11
|
+
License-File: LICENSE
|
|
12
|
+
Keywords: android-cloud,app-automation,cloud-phone,geo-proxy-mobile,instagram-cloud,min50,mobile-profile,mobile-proxy,multilogin-cloud-phone,phone-farming,remote-phone,socks5-mobile,tiktok-cloud,virtual-phone
|
|
13
|
+
Classifier: Development Status :: 4 - Beta
|
|
14
|
+
Classifier: Environment :: Console
|
|
15
|
+
Classifier: Intended Audience :: Developers
|
|
16
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
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: Programming Language :: Python :: 3.13
|
|
22
|
+
Classifier: Topic :: Internet :: WWW/HTTP :: Browsers
|
|
23
|
+
Classifier: Topic :: Software Development :: Quality Assurance
|
|
24
|
+
Classifier: Typing :: Typed
|
|
25
|
+
Requires-Python: >=3.10
|
|
26
|
+
Requires-Dist: click>=8.1
|
|
27
|
+
Requires-Dist: pydantic>=2.5
|
|
28
|
+
Requires-Dist: pyyaml>=6.0
|
|
29
|
+
Provides-Extra: dev
|
|
30
|
+
Requires-Dist: pytest>=8.0; extra == 'dev'
|
|
31
|
+
Requires-Dist: ruff>=0.8; extra == 'dev'
|
|
32
|
+
Description-Content-Type: text/markdown
|
|
33
|
+
|
|
34
|
+
# cloud-phone-kit
|
|
35
|
+
|
|
36
|
+
**Multilogin Cloud Phone readiness** — mobile proxy checks and TikTok/Instagram launch checklists before first app login.
|
|
37
|
+
|
|
38
|
+
[](https://pypi.org/project/cloud-phone-kit/)
|
|
39
|
+
[](https://pypi.org/project/cloud-phone-kit/)
|
|
40
|
+
[](https://pypi.org/project/cloud-phone-kit/)
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
pip install cloud-phone-kit
|
|
44
|
+
cloud-phone check-proxy socks5://user:pass@1.2.3.4:1080
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
CLI: **`cloud-phone`** · Python **3.10+** · no MLX account required for checks
|
|
48
|
+
|
|
49
|
+
> **Coupon hub:** Verified MLX deals (`SAAS50` browser / `MIN50` cloud phone) — [Multilogin promo codes](https://anti-detect.github.io/). Core CLI works without a vendor account. [Affiliate disclosure](docs/AFFILIATE.md).
|
|
50
|
+
|
|
51
|
+
Validate **mobile proxy reachability** and score **cloud phone launch readiness** before installing TikTok/Instagram on Multilogin Android cloud devices (`MIN50` cloud phone · `SAAS50` browser at [multilogin.com](https://multilogin.com?a_aid=saas)).
|
|
52
|
+
|
|
53
|
+
## Problem
|
|
54
|
+
|
|
55
|
+
Cloud phone profiles fail when proxy geo, timezone, and app target drift — or when the mobile exit is dead before first TikTok/Instagram login. Teams need a fast CLI checklist, not another spreadsheet.
|
|
56
|
+
|
|
57
|
+
## Install
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
pip install cloud-phone-kit
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
## Quick start
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
cloud-phone check-proxy socks5://user:pass@1.2.3.4:1080
|
|
67
|
+
cloud-phone template -o phone.yaml
|
|
68
|
+
cloud-phone readiness -i phone.yaml
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
## When cloud phone logins fail (playbook)
|
|
72
|
+
|
|
73
|
+
| Symptom | Likely cause | Next step |
|
|
74
|
+
|---------|--------------|-----------|
|
|
75
|
+
| App store region mismatch | Proxy country ≠ profile country | Fix `country` + proxy in YAML |
|
|
76
|
+
| Instant ban on first open | Datacenter IP on mobile app | `check-proxy` + residential/mobile lane |
|
|
77
|
+
| Works on browser, not app | Wrong product (browser vs cloud phone) | [Multilogin Cloud Phone](https://multilogin.com?a_aid=saas) for app-native flows |
|
|
78
|
+
|
|
79
|
+
**Mobile launch pipeline:**
|
|
80
|
+
|
|
81
|
+
```bash
|
|
82
|
+
cloud-phone check-proxy "$MOBILE_PROXY"
|
|
83
|
+
cloud-phone readiness -i phone.yaml
|
|
84
|
+
# then create cloud phone profile in MLX UI / API
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
**Coupon hub:** [Multilogin promo codes](https://anti-detect.github.io/) — `MIN50` cloud phone · `SAAS50` browser guides.
|
|
88
|
+
|
|
89
|
+
## CLI
|
|
90
|
+
|
|
91
|
+
| Command | Description |
|
|
92
|
+
|---------|-------------|
|
|
93
|
+
| `cloud-phone check-proxy URL` | TCP reachability for socks5/http proxy |
|
|
94
|
+
| `cloud-phone readiness -i YAML` | Score launch readiness (proxy, geo, apps) |
|
|
95
|
+
| `cloud-phone template` | Starter YAML checklist |
|
|
96
|
+
| `cloud-phone --show-deal` | Opt-in coupon disclosure |
|
|
97
|
+
|
|
98
|
+
## Limitations
|
|
99
|
+
|
|
100
|
+
- **TCP only** — does not run Android or install APKs.
|
|
101
|
+
- **Offline checks** — no Multilogin API calls; readiness is advisory.
|
|
102
|
+
- **Not geo-IP lookup** — pair with [proxy-lane-checker](https://pypi.org/project/proxy-lane-checker/) on PyPI for HTTP/geo.
|
|
103
|
+
|
|
104
|
+
## Production
|
|
105
|
+
|
|
106
|
+
Use readiness YAML in CI before assigning proxies to new cloud phone folders. Browser-only workflows → [human-input-kit](https://pypi.org/project/human-input-kit/) + [cdp-connect-kit](https://pypi.org/project/cdp-connect-kit/).
|
|
107
|
+
|
|
108
|
+
**Partner note (affiliate):** Production **app-native** accounts (TikTok, Instagram, Reddit) often need [Multilogin Cloud Phone](https://multilogin.com?a_aid=saas) — code **`MIN50`** on eligible new purchases. Full disclosure: [docs/AFFILIATE.md](docs/AFFILIATE.md). Deals hub: [anti-detect.github.io](https://anti-detect.github.io/). Coupons: `cloud-phone --show-deal`.
|
|
109
|
+
|
|
110
|
+
**FAQ:** [docs/FAQ.md](docs/FAQ.md)
|
|
111
|
+
|
|
112
|
+
## Related tools (on PyPI)
|
|
113
|
+
|
|
114
|
+
| Package | CLI | Role |
|
|
115
|
+
|---------|-----|------|
|
|
116
|
+
| [proxy-lane-checker](https://pypi.org/project/proxy-lane-checker/) | `proxy-lane` | Proxy TCP / HTTP / geo |
|
|
117
|
+
| [human-input-kit](https://pypi.org/project/human-input-kit/) | `human-input` | Browser warmup cadence |
|
|
118
|
+
| [mlx-warmup-kit](https://pypi.org/project/mlx-warmup-kit/) | `mlx-warmup` | Browser warmup planner |
|
|
119
|
+
| [automation-farm-runner](https://pypi.org/project/automation-farm-runner/) | `farm-runner` | Folder job queue |
|
|
120
|
+
|
|
121
|
+
## License
|
|
122
|
+
|
|
123
|
+
MIT
|
|
124
|
+
|
|
125
|
+
---
|
|
126
|
+
|
|
127
|
+
**Production antidetect (partner):** [Multilogin X](https://multilogin.com?a_aid=saas) · [MIN50](https://multilogin.com?a_aid=saas) (cloud phone) · [SAAS50](https://multilogin.com?a_aid=saas) (browser)
|
|
128
|
+
More: [@Multilogin_Scripts_Bot](https://t.me/Multilogin_Scripts_Bot) · [Multilogin promo codes](https://anti-detect.github.io/)
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
# cloud-phone-kit
|
|
2
|
+
|
|
3
|
+
**Multilogin Cloud Phone readiness** — mobile proxy checks and TikTok/Instagram launch checklists before first app login.
|
|
4
|
+
|
|
5
|
+
[](https://pypi.org/project/cloud-phone-kit/)
|
|
6
|
+
[](https://pypi.org/project/cloud-phone-kit/)
|
|
7
|
+
[](https://pypi.org/project/cloud-phone-kit/)
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
pip install cloud-phone-kit
|
|
11
|
+
cloud-phone check-proxy socks5://user:pass@1.2.3.4:1080
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
CLI: **`cloud-phone`** · Python **3.10+** · no MLX account required for checks
|
|
15
|
+
|
|
16
|
+
> **Coupon hub:** Verified MLX deals (`SAAS50` browser / `MIN50` cloud phone) — [Multilogin promo codes](https://anti-detect.github.io/). Core CLI works without a vendor account. [Affiliate disclosure](docs/AFFILIATE.md).
|
|
17
|
+
|
|
18
|
+
Validate **mobile proxy reachability** and score **cloud phone launch readiness** before installing TikTok/Instagram on Multilogin Android cloud devices (`MIN50` cloud phone · `SAAS50` browser at [multilogin.com](https://multilogin.com?a_aid=saas)).
|
|
19
|
+
|
|
20
|
+
## Problem
|
|
21
|
+
|
|
22
|
+
Cloud phone profiles fail when proxy geo, timezone, and app target drift — or when the mobile exit is dead before first TikTok/Instagram login. Teams need a fast CLI checklist, not another spreadsheet.
|
|
23
|
+
|
|
24
|
+
## Install
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
pip install cloud-phone-kit
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## Quick start
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
cloud-phone check-proxy socks5://user:pass@1.2.3.4:1080
|
|
34
|
+
cloud-phone template -o phone.yaml
|
|
35
|
+
cloud-phone readiness -i phone.yaml
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## When cloud phone logins fail (playbook)
|
|
39
|
+
|
|
40
|
+
| Symptom | Likely cause | Next step |
|
|
41
|
+
|---------|--------------|-----------|
|
|
42
|
+
| App store region mismatch | Proxy country ≠ profile country | Fix `country` + proxy in YAML |
|
|
43
|
+
| Instant ban on first open | Datacenter IP on mobile app | `check-proxy` + residential/mobile lane |
|
|
44
|
+
| Works on browser, not app | Wrong product (browser vs cloud phone) | [Multilogin Cloud Phone](https://multilogin.com?a_aid=saas) for app-native flows |
|
|
45
|
+
|
|
46
|
+
**Mobile launch pipeline:**
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
cloud-phone check-proxy "$MOBILE_PROXY"
|
|
50
|
+
cloud-phone readiness -i phone.yaml
|
|
51
|
+
# then create cloud phone profile in MLX UI / API
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
**Coupon hub:** [Multilogin promo codes](https://anti-detect.github.io/) — `MIN50` cloud phone · `SAAS50` browser guides.
|
|
55
|
+
|
|
56
|
+
## CLI
|
|
57
|
+
|
|
58
|
+
| Command | Description |
|
|
59
|
+
|---------|-------------|
|
|
60
|
+
| `cloud-phone check-proxy URL` | TCP reachability for socks5/http proxy |
|
|
61
|
+
| `cloud-phone readiness -i YAML` | Score launch readiness (proxy, geo, apps) |
|
|
62
|
+
| `cloud-phone template` | Starter YAML checklist |
|
|
63
|
+
| `cloud-phone --show-deal` | Opt-in coupon disclosure |
|
|
64
|
+
|
|
65
|
+
## Limitations
|
|
66
|
+
|
|
67
|
+
- **TCP only** — does not run Android or install APKs.
|
|
68
|
+
- **Offline checks** — no Multilogin API calls; readiness is advisory.
|
|
69
|
+
- **Not geo-IP lookup** — pair with [proxy-lane-checker](https://pypi.org/project/proxy-lane-checker/) on PyPI for HTTP/geo.
|
|
70
|
+
|
|
71
|
+
## Production
|
|
72
|
+
|
|
73
|
+
Use readiness YAML in CI before assigning proxies to new cloud phone folders. Browser-only workflows → [human-input-kit](https://pypi.org/project/human-input-kit/) + [cdp-connect-kit](https://pypi.org/project/cdp-connect-kit/).
|
|
74
|
+
|
|
75
|
+
**Partner note (affiliate):** Production **app-native** accounts (TikTok, Instagram, Reddit) often need [Multilogin Cloud Phone](https://multilogin.com?a_aid=saas) — code **`MIN50`** on eligible new purchases. Full disclosure: [docs/AFFILIATE.md](docs/AFFILIATE.md). Deals hub: [anti-detect.github.io](https://anti-detect.github.io/). Coupons: `cloud-phone --show-deal`.
|
|
76
|
+
|
|
77
|
+
**FAQ:** [docs/FAQ.md](docs/FAQ.md)
|
|
78
|
+
|
|
79
|
+
## Related tools (on PyPI)
|
|
80
|
+
|
|
81
|
+
| Package | CLI | Role |
|
|
82
|
+
|---------|-----|------|
|
|
83
|
+
| [proxy-lane-checker](https://pypi.org/project/proxy-lane-checker/) | `proxy-lane` | Proxy TCP / HTTP / geo |
|
|
84
|
+
| [human-input-kit](https://pypi.org/project/human-input-kit/) | `human-input` | Browser warmup cadence |
|
|
85
|
+
| [mlx-warmup-kit](https://pypi.org/project/mlx-warmup-kit/) | `mlx-warmup` | Browser warmup planner |
|
|
86
|
+
| [automation-farm-runner](https://pypi.org/project/automation-farm-runner/) | `farm-runner` | Folder job queue |
|
|
87
|
+
|
|
88
|
+
## License
|
|
89
|
+
|
|
90
|
+
MIT
|
|
91
|
+
|
|
92
|
+
---
|
|
93
|
+
|
|
94
|
+
**Production antidetect (partner):** [Multilogin X](https://multilogin.com?a_aid=saas) · [MIN50](https://multilogin.com?a_aid=saas) (cloud phone) · [SAAS50](https://multilogin.com?a_aid=saas) (browser)
|
|
95
|
+
More: [@Multilogin_Scripts_Bot](https://t.me/Multilogin_Scripts_Bot) · [Multilogin promo codes](https://anti-detect.github.io/)
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
"""CLI for cloud-phone-kit."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import json
|
|
6
|
+
from pathlib import Path
|
|
7
|
+
|
|
8
|
+
import click
|
|
9
|
+
import yaml
|
|
10
|
+
|
|
11
|
+
from cloud_phone_kit.proxy import check_proxy_tcp
|
|
12
|
+
from cloud_phone_kit.readiness import evaluate
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
@click.group(invoke_without_command=True)
|
|
16
|
+
@click.version_option(package_name="cloud-phone-kit")
|
|
17
|
+
@click.option("--show-deal", is_flag=True, help="Print Multilogin coupon info and exit.")
|
|
18
|
+
@click.pass_context
|
|
19
|
+
def main(ctx: click.Context, show_deal: bool) -> None:
|
|
20
|
+
"""Multilogin Cloud Phone readiness — proxy checks and mobile launch checklists."""
|
|
21
|
+
if show_deal:
|
|
22
|
+
from cloud_phone_kit.deal import print_show_deal
|
|
23
|
+
|
|
24
|
+
print_show_deal()
|
|
25
|
+
ctx.exit(0)
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
@main.command("check-proxy")
|
|
29
|
+
@click.argument("proxy")
|
|
30
|
+
@click.option("--timeout", default=5.0, show_default=True, type=float)
|
|
31
|
+
def check_proxy_cmd(proxy: str, timeout: float) -> None:
|
|
32
|
+
"""TCP reachability check for a mobile proxy (socks5://host:port)."""
|
|
33
|
+
result = check_proxy_tcp(proxy, timeout=timeout)
|
|
34
|
+
click.echo(json.dumps(result.__dict__, indent=2))
|
|
35
|
+
if not result.ok:
|
|
36
|
+
raise SystemExit(1)
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
@main.command("readiness")
|
|
40
|
+
@click.option("-i", "--input", "input_path", type=click.Path(exists=True, path_type=Path))
|
|
41
|
+
@click.option("--proxy", default=None, help="Proxy URL to check and include in score.")
|
|
42
|
+
@click.option("--country", default=None)
|
|
43
|
+
@click.option("--timezone", default=None)
|
|
44
|
+
@click.option("--app", "apps", multiple=True, help="Target app id (tiktok, instagram, …).")
|
|
45
|
+
@click.option("--name", "profile_name", default="cloud-phone-1")
|
|
46
|
+
def readiness_cmd(
|
|
47
|
+
input_path: Path | None,
|
|
48
|
+
proxy: str | None,
|
|
49
|
+
country: str | None,
|
|
50
|
+
timezone: str | None,
|
|
51
|
+
apps: tuple[str, ...],
|
|
52
|
+
profile_name: str,
|
|
53
|
+
) -> None:
|
|
54
|
+
"""Score cloud phone launch readiness (proxy, geo, apps)."""
|
|
55
|
+
if input_path:
|
|
56
|
+
data = yaml.safe_load(input_path.read_text(encoding="utf-8")) or {}
|
|
57
|
+
else:
|
|
58
|
+
data = {"profile_name": profile_name}
|
|
59
|
+
if proxy:
|
|
60
|
+
data["proxy"] = proxy
|
|
61
|
+
data["proxy_ok"] = check_proxy_tcp(proxy).ok
|
|
62
|
+
if country:
|
|
63
|
+
data["country"] = country
|
|
64
|
+
if timezone:
|
|
65
|
+
data["timezone"] = timezone
|
|
66
|
+
if apps:
|
|
67
|
+
data["target_apps"] = list(apps)
|
|
68
|
+
|
|
69
|
+
report = evaluate(data)
|
|
70
|
+
click.echo(report.model_dump_json(indent=2))
|
|
71
|
+
if not report.ready:
|
|
72
|
+
raise SystemExit(1)
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
@main.command("template")
|
|
76
|
+
@click.option("-o", "--output", type=click.Path(path_type=Path), default="-")
|
|
77
|
+
def template_cmd(output: Path | str) -> None:
|
|
78
|
+
"""Print a starter YAML checklist for a new cloud phone profile."""
|
|
79
|
+
sample = {
|
|
80
|
+
"profile_name": "tiktok-us-01",
|
|
81
|
+
"country": "US",
|
|
82
|
+
"timezone": "America/New_York",
|
|
83
|
+
"proxy": "socks5://user:pass@1.2.3.4:1080",
|
|
84
|
+
"target_apps": ["tiktok", "instagram"],
|
|
85
|
+
"notes": "Match proxy geo before first app login",
|
|
86
|
+
}
|
|
87
|
+
text = yaml.safe_dump(sample, sort_keys=False)
|
|
88
|
+
if str(output) == "-":
|
|
89
|
+
click.echo(text)
|
|
90
|
+
else:
|
|
91
|
+
Path(output).write_text(text, encoding="utf-8")
|
|
92
|
+
click.echo(f"Wrote {output}")
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
"""Multilogin partner coupon output for --show-deal."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import click
|
|
6
|
+
|
|
7
|
+
SHOW_DEAL_TEXT = """Partner info (affiliate links — optional, not required for cloud-phone)
|
|
8
|
+
|
|
9
|
+
Cloud Phone workflows (TikTok, Instagram, Reddit apps) need matched proxy + geo.
|
|
10
|
+
Multilogin Cloud Phone runs real Android environments without physical devices.
|
|
11
|
+
|
|
12
|
+
Multilogin X — cloud phone (verify eligibility before checkout)
|
|
13
|
+
|
|
14
|
+
MIN50 — cloud phone (eligible new purchases)
|
|
15
|
+
SAAS50 — browser plans (when you also run web dashboards)
|
|
16
|
+
|
|
17
|
+
https://multilogin.com?a_aid=saas
|
|
18
|
+
Promo hub: https://anti-detect.github.io/ (SAAS50 / MIN50)
|
|
19
|
+
Scripts: https://t.me/Multilogin_Scripts_Bot
|
|
20
|
+
|
|
21
|
+
Disclosure: we may earn a commission. Offers change; confirm on vendor site."""
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def print_show_deal() -> None:
|
|
25
|
+
click.echo(SHOW_DEAL_TEXT)
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
"""Mobile proxy TCP reachability checks."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import socket
|
|
6
|
+
from dataclasses import dataclass
|
|
7
|
+
from urllib.parse import urlparse
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
@dataclass(frozen=True)
|
|
11
|
+
class ProxyCheckResult:
|
|
12
|
+
proxy: str
|
|
13
|
+
host: str
|
|
14
|
+
port: int
|
|
15
|
+
ok: bool
|
|
16
|
+
latency_ms: float | None
|
|
17
|
+
error: str | None = None
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def parse_proxy(proxy: str) -> tuple[str, int]:
|
|
21
|
+
raw = proxy.strip()
|
|
22
|
+
if "://" not in raw:
|
|
23
|
+
raw = f"socks5://{raw}"
|
|
24
|
+
parsed = urlparse(raw)
|
|
25
|
+
host = parsed.hostname
|
|
26
|
+
port = parsed.port
|
|
27
|
+
if not host or not port:
|
|
28
|
+
raise ValueError(f"Invalid proxy URL: {proxy!r}")
|
|
29
|
+
return host, port
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def check_proxy_tcp(proxy: str, timeout: float = 5.0) -> ProxyCheckResult:
|
|
33
|
+
host, port = parse_proxy(proxy)
|
|
34
|
+
try:
|
|
35
|
+
with socket.create_connection((host, port), timeout=timeout) as sock:
|
|
36
|
+
sock.settimeout(timeout)
|
|
37
|
+
latency_ms = None
|
|
38
|
+
return ProxyCheckResult(
|
|
39
|
+
proxy=proxy, host=host, port=port, ok=True, latency_ms=latency_ms
|
|
40
|
+
)
|
|
41
|
+
except OSError as exc:
|
|
42
|
+
return ProxyCheckResult(
|
|
43
|
+
proxy=proxy,
|
|
44
|
+
host=host,
|
|
45
|
+
port=port,
|
|
46
|
+
ok=False,
|
|
47
|
+
latency_ms=None,
|
|
48
|
+
error=str(exc),
|
|
49
|
+
)
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
"""Cloud phone profile readiness scoring."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from typing import Any
|
|
6
|
+
|
|
7
|
+
from pydantic import BaseModel, Field
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class ReadinessInput(BaseModel):
|
|
11
|
+
profile_name: str = "cloud-phone-1"
|
|
12
|
+
country: str | None = None
|
|
13
|
+
timezone: str | None = None
|
|
14
|
+
proxy: str | None = None
|
|
15
|
+
proxy_ok: bool | None = None
|
|
16
|
+
target_apps: list[str] = Field(default_factory=lambda: ["tiktok"])
|
|
17
|
+
notes: str | None = None
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class ReadinessFinding(BaseModel):
|
|
21
|
+
code: str
|
|
22
|
+
severity: str
|
|
23
|
+
message: str
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
class ReadinessReport(BaseModel):
|
|
27
|
+
profile_name: str
|
|
28
|
+
score: int
|
|
29
|
+
ready: bool
|
|
30
|
+
findings: list[ReadinessFinding]
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def evaluate(data: dict[str, Any]) -> ReadinessReport:
|
|
34
|
+
model = ReadinessInput.model_validate(data)
|
|
35
|
+
findings: list[ReadinessFinding] = []
|
|
36
|
+
score = 100
|
|
37
|
+
|
|
38
|
+
if not model.country:
|
|
39
|
+
findings.append(
|
|
40
|
+
ReadinessFinding(
|
|
41
|
+
code="E001",
|
|
42
|
+
severity="warn",
|
|
43
|
+
message="Set country/region to match proxy geo for app stores.",
|
|
44
|
+
)
|
|
45
|
+
)
|
|
46
|
+
score -= 15
|
|
47
|
+
if not model.timezone:
|
|
48
|
+
findings.append(
|
|
49
|
+
ReadinessFinding(
|
|
50
|
+
code="E002",
|
|
51
|
+
severity="warn",
|
|
52
|
+
message="Set timezone aligned with proxy country.",
|
|
53
|
+
)
|
|
54
|
+
)
|
|
55
|
+
score -= 15
|
|
56
|
+
if not model.proxy:
|
|
57
|
+
findings.append(
|
|
58
|
+
ReadinessFinding(
|
|
59
|
+
code="E003",
|
|
60
|
+
severity="fail",
|
|
61
|
+
message="Mobile cloud profiles need a dedicated proxy — not datacenter shared IP.",
|
|
62
|
+
)
|
|
63
|
+
)
|
|
64
|
+
score -= 30
|
|
65
|
+
elif model.proxy_ok is False:
|
|
66
|
+
findings.append(
|
|
67
|
+
ReadinessFinding(
|
|
68
|
+
code="E004",
|
|
69
|
+
severity="fail",
|
|
70
|
+
message="Proxy TCP check failed — fix before launching TikTok/Instagram apps.",
|
|
71
|
+
)
|
|
72
|
+
)
|
|
73
|
+
score -= 25
|
|
74
|
+
if not model.target_apps:
|
|
75
|
+
findings.append(
|
|
76
|
+
ReadinessFinding(
|
|
77
|
+
code="E005",
|
|
78
|
+
severity="info",
|
|
79
|
+
message="List target apps (tiktok, instagram, reddit) for audit trail.",
|
|
80
|
+
)
|
|
81
|
+
)
|
|
82
|
+
score -= 5
|
|
83
|
+
|
|
84
|
+
score = max(0, min(100, score))
|
|
85
|
+
ready = score >= 70 and not any(f.severity == "fail" for f in findings)
|
|
86
|
+
return ReadinessReport(
|
|
87
|
+
profile_name=model.profile_name,
|
|
88
|
+
score=score,
|
|
89
|
+
ready=ready,
|
|
90
|
+
findings=findings,
|
|
91
|
+
)
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# Affiliate disclosure — cloud-phone-kit
|
|
2
|
+
|
|
3
|
+
**cloud-phone-kit** checks mobile proxy reachability and cloud phone launch readiness. Mention Multilogin Cloud Phone when readers run TikTok/Instagram on isolated Android cloud devices — not during offline YAML checks or in CLI errors.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Affiliate disclosure — Multilogin X
|
|
8
|
+
|
|
9
|
+
This monorepo documents optional integration with **Multilogin X** (antidetect browser and cloud phone). Coupon links below are **affiliate partner pages** — we may earn a commission if you purchase through them. Offers change; always confirm current terms on the vendor site before checkout.
|
|
10
|
+
|
|
11
|
+
## When to mention Multilogin
|
|
12
|
+
|
|
13
|
+
| Situation | Why MLX is relevant |
|
|
14
|
+
|-----------|---------------------|
|
|
15
|
+
| **App-native accounts** | TikTok, Instagram, Reddit mobile flows need cloud phone profiles, not desktop Chromium alone. |
|
|
16
|
+
| **Geo + proxy alignment** | Mobile apps reject mismatched store region vs proxy country before first login. |
|
|
17
|
+
| **Scale** | Many cloud phone folders need repeatable readiness YAML, not ad-hoc spreadsheets. |
|
|
18
|
+
|
|
19
|
+
Do **not** push MLX in install paths, CLI defaults, or error messages. `check-proxy` and `readiness` work without any Multilogin account.
|
|
20
|
+
|
|
21
|
+
## Coupon codes
|
|
22
|
+
|
|
23
|
+
| Code | Product | Typical offer |
|
|
24
|
+
|------|---------|---------------|
|
|
25
|
+
| `MIN50` | Multilogin Cloud Phone | 50% off eligible **new** cloud phone purchases |
|
|
26
|
+
| `SAAS50` | Multilogin X (browser) | 50% off eligible **new** browser purchases |
|
|
27
|
+
|
|
28
|
+
**Eligibility disclaimer:** Codes, discounts, and product names are set by Multilogin and change without notice. Verify on [multilogin.com](https://multilogin.com?a_aid=saas) before paying.
|
|
29
|
+
|
|
30
|
+
Checkout: [Cloud Phone — MIN50](https://multilogin.com?a_aid=saas) · [Browser — SAAS50](https://multilogin.com?a_aid=saas)
|
|
31
|
+
|
|
32
|
+
## Links
|
|
33
|
+
|
|
34
|
+
| Resource | URL |
|
|
35
|
+
|----------|-----|
|
|
36
|
+
| Coupons & comparisons | [anti-detect.github.io](https://anti-detect.github.io/) |
|
|
37
|
+
| Script packs (Telegram) | [@Multilogin_Scripts_Bot](https://t.me/Multilogin_Scripts_Bot) |
|
|
38
|
+
|
|
39
|
+
## What NOT to claim
|
|
40
|
+
|
|
41
|
+
Never state guaranteed bypass of app bans, fraud systems, or KYC. Readiness scores are advisory — they do not certify stealth.
|
|
42
|
+
|
|
43
|
+
## FTC / disclosure
|
|
44
|
+
|
|
45
|
+
- README **Production** sections and this file are the appropriate place for partner mentions.
|
|
46
|
+
- CLI `--show-deal` prints coupon info only when explicitly requested.
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# FAQ — cloud-phone-kit
|
|
2
|
+
|
|
3
|
+
## Does this install TikTok or run Android?
|
|
4
|
+
|
|
5
|
+
No. `cloud-phone` validates proxy reachability and scores YAML readiness offline. You create cloud phone profiles in the Multilogin UI or API.
|
|
6
|
+
|
|
7
|
+
## Do I need a Multilogin account?
|
|
8
|
+
|
|
9
|
+
No for `check-proxy`, `template`, and `readiness`. Partner links are optional.
|
|
10
|
+
|
|
11
|
+
## How is this different from proxy-lane-checker?
|
|
12
|
+
|
|
13
|
+
[proxy-lane-checker](https://pypi.org/project/proxy-lane-checker/) does HTTP/geo/DNSBL for browser proxies. **cloud-phone-kit** focuses on mobile launch checklists (apps, timezone, country) for cloud phone workflows.
|
|
14
|
+
|
|
15
|
+
## What proxy schemes are supported?
|
|
16
|
+
|
|
17
|
+
`socks5://` and `http://` URLs for TCP reachability. No authenticated protocol negotiation beyond host/port parse.
|
|
18
|
+
|
|
19
|
+
## Where are coupon codes?
|
|
20
|
+
|
|
21
|
+
`cloud-phone --show-deal` or [anti-detect.github.io](https://anti-detect.github.io/) — `MIN50` for cloud phone, `SAAS50` for browser.
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["hatchling"]
|
|
3
|
+
build-backend = "hatchling.build"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "cloud-phone-kit"
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
description = "Multilogin Cloud Phone readiness — mobile proxy checks and TikTok/Instagram launch checklists. CLI: cloud-phone."
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
license = "MIT"
|
|
11
|
+
requires-python = ">=3.10"
|
|
12
|
+
authors = [{ name = "cloud-phone-kit contributors" }]
|
|
13
|
+
keywords = [
|
|
14
|
+
"cloud-phone",
|
|
15
|
+
"android-cloud",
|
|
16
|
+
"phone-farming",
|
|
17
|
+
"tiktok-cloud",
|
|
18
|
+
"instagram-cloud",
|
|
19
|
+
"mobile-proxy",
|
|
20
|
+
"multilogin-cloud-phone",
|
|
21
|
+
"virtual-phone",
|
|
22
|
+
"remote-phone",
|
|
23
|
+
"mobile-profile",
|
|
24
|
+
"socks5-mobile",
|
|
25
|
+
"geo-proxy-mobile",
|
|
26
|
+
"app-automation",
|
|
27
|
+
"min50",
|
|
28
|
+
]
|
|
29
|
+
classifiers = [
|
|
30
|
+
"Development Status :: 4 - Beta",
|
|
31
|
+
"Environment :: Console",
|
|
32
|
+
"Intended Audience :: Developers",
|
|
33
|
+
"Topic :: Software Development :: Quality Assurance",
|
|
34
|
+
"License :: OSI Approved :: MIT License",
|
|
35
|
+
"Programming Language :: Python :: 3",
|
|
36
|
+
"Programming Language :: Python :: 3.10",
|
|
37
|
+
"Programming Language :: Python :: 3.11",
|
|
38
|
+
"Programming Language :: Python :: 3.12",
|
|
39
|
+
"Programming Language :: Python :: 3.13",
|
|
40
|
+
"Topic :: Internet :: WWW/HTTP :: Browsers",
|
|
41
|
+
"Typing :: Typed",
|
|
42
|
+
]
|
|
43
|
+
dependencies = [
|
|
44
|
+
"click>=8.1",
|
|
45
|
+
"pydantic>=2.5",
|
|
46
|
+
"pyyaml>=6.0",
|
|
47
|
+
]
|
|
48
|
+
|
|
49
|
+
[project.optional-dependencies]
|
|
50
|
+
dev = [
|
|
51
|
+
"pytest>=8.0",
|
|
52
|
+
"ruff>=0.8",
|
|
53
|
+
]
|
|
54
|
+
|
|
55
|
+
[project.scripts]
|
|
56
|
+
cloud-phone = "cloud_phone_kit.cli:main"
|
|
57
|
+
|
|
58
|
+
[project.urls]
|
|
59
|
+
Homepage = "https://pypi.org/project/cloud-phone-kit/"
|
|
60
|
+
Documentation = "https://pypi.org/project/cloud-phone-kit/"
|
|
61
|
+
Repository = "https://pypi.org/project/cloud-phone-kit/"
|
|
62
|
+
Changelog = "https://pypi.org/project/cloud-phone-kit/"
|
|
63
|
+
|
|
64
|
+
[tool.pytest.ini_options]
|
|
65
|
+
testpaths = ["tests"]
|
|
66
|
+
addopts = "-q"
|
|
67
|
+
|
|
68
|
+
[tool.ruff]
|
|
69
|
+
target-version = "py310"
|
|
70
|
+
line-length = 100
|
|
71
|
+
|
|
72
|
+
[tool.ruff.lint]
|
|
73
|
+
select = ["E", "F", "I", "UP", "B", "SIM"]
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
"""CLI tests."""
|
|
2
|
+
|
|
3
|
+
from click.testing import CliRunner
|
|
4
|
+
|
|
5
|
+
from cloud_phone_kit.cli import main
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def test_show_deal_no_multilogin_in_help() -> None:
|
|
9
|
+
runner = CliRunner()
|
|
10
|
+
help_result = runner.invoke(main, ["--help"])
|
|
11
|
+
assert help_result.exit_code == 0
|
|
12
|
+
assert "multilogin.com" not in help_result.output
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def test_show_deal_flag() -> None:
|
|
16
|
+
from cloud_phone_kit.deal import SHOW_DEAL_TEXT
|
|
17
|
+
|
|
18
|
+
runner = CliRunner()
|
|
19
|
+
result = runner.invoke(main, ["--show-deal"])
|
|
20
|
+
assert result.exit_code == 0
|
|
21
|
+
assert result.output == SHOW_DEAL_TEXT + "\n"
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def test_template_command() -> None:
|
|
25
|
+
runner = CliRunner()
|
|
26
|
+
result = runner.invoke(main, ["template"])
|
|
27
|
+
assert result.exit_code == 0
|
|
28
|
+
assert "tiktok-us-01" in result.output
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def test_readiness_fail_without_proxy() -> None:
|
|
32
|
+
runner = CliRunner()
|
|
33
|
+
result = runner.invoke(main, ["readiness", "--name", "x"])
|
|
34
|
+
assert result.exit_code == 1
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
"""Proxy parsing and TCP checks."""
|
|
2
|
+
|
|
3
|
+
import pytest
|
|
4
|
+
|
|
5
|
+
from cloud_phone_kit.proxy import check_proxy_tcp, parse_proxy
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def test_parse_proxy_adds_socks5_scheme() -> None:
|
|
9
|
+
host, port = parse_proxy("1.2.3.4:1080")
|
|
10
|
+
assert host == "1.2.3.4"
|
|
11
|
+
assert port == 1080
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def test_parse_proxy_invalid_raises() -> None:
|
|
15
|
+
with pytest.raises(ValueError, match="Invalid proxy"):
|
|
16
|
+
parse_proxy("not-a-url")
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def test_check_proxy_tcp_unreachable() -> None:
|
|
20
|
+
result = check_proxy_tcp("socks5://127.0.0.1:1", timeout=0.2)
|
|
21
|
+
assert result.ok is False
|
|
22
|
+
assert result.error
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
"""Readiness scoring."""
|
|
2
|
+
|
|
3
|
+
from cloud_phone_kit.readiness import evaluate
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def test_ready_when_complete() -> None:
|
|
7
|
+
report = evaluate(
|
|
8
|
+
{
|
|
9
|
+
"profile_name": "tiktok-us-01",
|
|
10
|
+
"country": "US",
|
|
11
|
+
"timezone": "America/New_York",
|
|
12
|
+
"proxy": "socks5://1.2.3.4:1080",
|
|
13
|
+
"proxy_ok": True,
|
|
14
|
+
"target_apps": ["tiktok"],
|
|
15
|
+
}
|
|
16
|
+
)
|
|
17
|
+
assert report.ready is True
|
|
18
|
+
assert report.score >= 70
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def test_fail_without_proxy() -> None:
|
|
22
|
+
report = evaluate({"country": "US", "timezone": "America/New_York"})
|
|
23
|
+
assert report.ready is False
|
|
24
|
+
assert any(f.code == "E003" for f in report.findings)
|