ipok 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.
ipok-0.1.0/.gitignore ADDED
@@ -0,0 +1,19 @@
1
+ # secrets — NEVER commit
2
+ .env
3
+ .env.*
4
+ *.token
5
+
6
+ # python build
7
+ dist/
8
+ build/
9
+ *.egg-info/
10
+ __pycache__/
11
+ *.pyc
12
+ .venv/
13
+
14
+ # node
15
+ node_modules/
16
+ *.tgz
17
+
18
+ # misc
19
+ .DS_Store
ipok-0.1.0/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 IPOK (ipok.io)
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.
ipok-0.1.0/PKG-INFO ADDED
@@ -0,0 +1,132 @@
1
+ Metadata-Version: 2.4
2
+ Name: ipok
3
+ Version: 0.1.0
4
+ Summary: Terminal IP purity / risk / AI-availability check — powered by ipok.io
5
+ Project-URL: Homepage, https://ipok.io
6
+ Project-URL: Repository, https://github.com/szp2005/ipok-cli
7
+ Author: ipok.io
8
+ License: MIT
9
+ License-File: LICENSE
10
+ Keywords: cli,fraud,geoip,ip,ip-purity,ip-quality,ip-reputation,proxy-detection,risk-score,vpn-detection
11
+ Classifier: Development Status :: 4 - Beta
12
+ Classifier: Environment :: Console
13
+ Classifier: Intended Audience :: Developers
14
+ Classifier: Intended Audience :: System Administrators
15
+ Classifier: License :: OSI Approved :: MIT License
16
+ Classifier: Programming Language :: Python :: 3
17
+ Classifier: Topic :: Internet
18
+ Classifier: Topic :: Security
19
+ Classifier: Topic :: System :: Networking
20
+ Requires-Python: >=3.8
21
+ Description-Content-Type: text/markdown
22
+
23
+ # IPOK CLI
24
+
25
+ [![IP risk](https://ipok.io/api/badge?ip=1.1.1.1&label=demo%20IP)](https://ipok.io/?ip=1.1.1.1)
26
+
27
+ > Terminal IP **purity / risk / AI-availability** check — powered by [ipok.io](https://ipok.io)
28
+
29
+ Check any IP's quality from your VPS or terminal in one line: risk score, residential vs datacenter, **native IP**, whether it can use **ChatGPT / Claude / Gemini**, use-case fit for **TikTok / e-commerce / social / AI**, and more.
30
+
31
+ 一行命令测 IP 纯净度 / 风险值 / 能不能用 AI —— 由 [ipok.io](https://ipok.io) 提供数据。
32
+
33
+ > 🧩 Prefer a browser? Get the **[IPOK Chrome extension](https://chromewebstore.google.com/detail/jnbkfmgldcchpdgnegafakbcnmkdhiai)** — one click to check your current IP's purity. ·
34
+ > 想用浏览器?装 **[IPOK Chrome 插件](https://chromewebstore.google.com/detail/jnbkfmgldcchpdgnegafakbcnmkdhiai)**,一键查当前 IP 纯净度。
35
+
36
+ ```
37
+ IPOK ip check ipok.io
38
+ ----------------------------------------------
39
+ IP 1.1.1.1 IPv4
40
+ Location Australia / South Brisbane
41
+ ASN AS13335 CLOUDFLARENET
42
+ Type business native: broadcast
43
+ Risk 11/100 Pristine
44
+ Signals hosting
45
+ AI ChatGPT:OK Claude:OK Gemini:OK
46
+ Use-case tiktok ** ecommerce ** social ** ai *****
47
+ Sources ip-api=55, Scamalytics=0, proxycheck=0, AbuseIPDB=0, ipapi.is=30, StopForumSpam=0
48
+ ----------------------------------------------
49
+ full report: https://ipok.io/?ip=1.1.1.1
50
+ ```
51
+
52
+ ## Install
53
+
54
+ Pick whichever fits your stack — all give you the same `ipok` command:
55
+
56
+ ```bash
57
+ # Node (no install, run once)
58
+ npx ipok-cli # check this machine's egress IP
59
+ npx ipok-cli 1.1.1.1 # check a specific IP
60
+
61
+ # Python
62
+ pip install ipok # then: ipok / ipok 1.1.1.1
63
+ pipx run ipok 1.1.1.1 # zero-install one-off
64
+
65
+ # Homebrew (macOS / Linux)
66
+ brew install szp2005/ipok/ipok
67
+ ```
68
+
69
+ ### Usage
70
+
71
+ ```bash
72
+ ipok # check this machine's egress IP
73
+ ipok 1.1.1.1 # check a specific IP
74
+ ipok --json 1.1.1.1 # raw JSON
75
+ ipok --help
76
+ ```
77
+
78
+ Set `IPOK_API` to point at a self-hosted endpoint; set `NO_COLOR=1` to disable colors.
79
+
80
+ ### No-install one-liner (servers / CI)
81
+
82
+ Just `curl` + `python3`, nothing to install — ideal on a bare VPS:
83
+
84
+ ```bash
85
+ bash <(curl -sL https://raw.githubusercontent.com/szp2005/ipok-cli/main/ipok.sh) # this server's IP
86
+ bash <(curl -sL https://raw.githubusercontent.com/szp2005/ipok-cli/main/ipok.sh) 1.1.1.1 # a specific IP
87
+ ```
88
+
89
+ ## Streaming / AI unlock (run on the server)
90
+
91
+ Test what **this server's exit IP** can unlock — Netflix (full / originals-only / blocked + region), ChatGPT region support, YouTube Premium, TikTok:
92
+
93
+ ```bash
94
+ bash <(curl -sL https://raw.githubusercontent.com/szp2005/ipok-cli/main/media.sh)
95
+ ```
96
+
97
+ Results reflect the server's outbound IP (the proxy/VPS use-case). Streaming providers change endpoints often, so treat results as best-effort.
98
+
99
+ ## Why
100
+
101
+ Most IP-purity tools give a single black-box score. IPOK aggregates multiple risk sources and shows **why** an IP is flagged, plus AI-service availability and use-case fit — the stuff that actually matters for proxies, cross-border, and AI accounts.
102
+
103
+ ## Free API (no auth, CORS-enabled)
104
+
105
+ The CLI just calls IPOK's public API. You can too:
106
+
107
+ ```bash
108
+ curl "https://ipok.io/api/ip?ip=1.1.1.1" # full IP report (JSON)
109
+ curl "https://ipok.io/api/bgp?asn=AS13335&ip=1.1.1.1" # BGP upstreams/downstreams (RIPEstat)
110
+ curl "https://ipok.io/api/reverse-ip?ip=1.1.1.1" # domains hosted on the IP
111
+ ```
112
+
113
+ Docs: <https://ipok.io/developers>
114
+
115
+ ### Response shape (`/api/ip`, excerpt)
116
+
117
+ ```jsonc
118
+ {
119
+ "geo": { "ip", "version", "country", "city", "asn", "asName", "isp", "lat", "lon" },
120
+ "ipType": "residential | hosting | mobile",
121
+ "risk": 0,
122
+ "nativeType": "native | broadcast | unknown",
123
+ "scenarios": [{ "key": "tiktok", "stars": 3, "verdict": "try" }],
124
+ "services": [{ "key": "chatgpt", "status": "available" }],
125
+ "sources": [{ "source": "ip-api", "risk": 10, "flags": {} }],
126
+ "rdap": { "registry", "country", "registered", "org" }
127
+ }
128
+ ```
129
+
130
+ ## License
131
+
132
+ MIT — see [LICENSE](./LICENSE). Not affiliated with any provider; data is best-effort and for diagnostics only.
ipok-0.1.0/README.md ADDED
@@ -0,0 +1,110 @@
1
+ # IPOK CLI
2
+
3
+ [![IP risk](https://ipok.io/api/badge?ip=1.1.1.1&label=demo%20IP)](https://ipok.io/?ip=1.1.1.1)
4
+
5
+ > Terminal IP **purity / risk / AI-availability** check — powered by [ipok.io](https://ipok.io)
6
+
7
+ Check any IP's quality from your VPS or terminal in one line: risk score, residential vs datacenter, **native IP**, whether it can use **ChatGPT / Claude / Gemini**, use-case fit for **TikTok / e-commerce / social / AI**, and more.
8
+
9
+ 一行命令测 IP 纯净度 / 风险值 / 能不能用 AI —— 由 [ipok.io](https://ipok.io) 提供数据。
10
+
11
+ > 🧩 Prefer a browser? Get the **[IPOK Chrome extension](https://chromewebstore.google.com/detail/jnbkfmgldcchpdgnegafakbcnmkdhiai)** — one click to check your current IP's purity. ·
12
+ > 想用浏览器?装 **[IPOK Chrome 插件](https://chromewebstore.google.com/detail/jnbkfmgldcchpdgnegafakbcnmkdhiai)**,一键查当前 IP 纯净度。
13
+
14
+ ```
15
+ IPOK ip check ipok.io
16
+ ----------------------------------------------
17
+ IP 1.1.1.1 IPv4
18
+ Location Australia / South Brisbane
19
+ ASN AS13335 CLOUDFLARENET
20
+ Type business native: broadcast
21
+ Risk 11/100 Pristine
22
+ Signals hosting
23
+ AI ChatGPT:OK Claude:OK Gemini:OK
24
+ Use-case tiktok ** ecommerce ** social ** ai *****
25
+ Sources ip-api=55, Scamalytics=0, proxycheck=0, AbuseIPDB=0, ipapi.is=30, StopForumSpam=0
26
+ ----------------------------------------------
27
+ full report: https://ipok.io/?ip=1.1.1.1
28
+ ```
29
+
30
+ ## Install
31
+
32
+ Pick whichever fits your stack — all give you the same `ipok` command:
33
+
34
+ ```bash
35
+ # Node (no install, run once)
36
+ npx ipok-cli # check this machine's egress IP
37
+ npx ipok-cli 1.1.1.1 # check a specific IP
38
+
39
+ # Python
40
+ pip install ipok # then: ipok / ipok 1.1.1.1
41
+ pipx run ipok 1.1.1.1 # zero-install one-off
42
+
43
+ # Homebrew (macOS / Linux)
44
+ brew install szp2005/ipok/ipok
45
+ ```
46
+
47
+ ### Usage
48
+
49
+ ```bash
50
+ ipok # check this machine's egress IP
51
+ ipok 1.1.1.1 # check a specific IP
52
+ ipok --json 1.1.1.1 # raw JSON
53
+ ipok --help
54
+ ```
55
+
56
+ Set `IPOK_API` to point at a self-hosted endpoint; set `NO_COLOR=1` to disable colors.
57
+
58
+ ### No-install one-liner (servers / CI)
59
+
60
+ Just `curl` + `python3`, nothing to install — ideal on a bare VPS:
61
+
62
+ ```bash
63
+ bash <(curl -sL https://raw.githubusercontent.com/szp2005/ipok-cli/main/ipok.sh) # this server's IP
64
+ bash <(curl -sL https://raw.githubusercontent.com/szp2005/ipok-cli/main/ipok.sh) 1.1.1.1 # a specific IP
65
+ ```
66
+
67
+ ## Streaming / AI unlock (run on the server)
68
+
69
+ Test what **this server's exit IP** can unlock — Netflix (full / originals-only / blocked + region), ChatGPT region support, YouTube Premium, TikTok:
70
+
71
+ ```bash
72
+ bash <(curl -sL https://raw.githubusercontent.com/szp2005/ipok-cli/main/media.sh)
73
+ ```
74
+
75
+ Results reflect the server's outbound IP (the proxy/VPS use-case). Streaming providers change endpoints often, so treat results as best-effort.
76
+
77
+ ## Why
78
+
79
+ Most IP-purity tools give a single black-box score. IPOK aggregates multiple risk sources and shows **why** an IP is flagged, plus AI-service availability and use-case fit — the stuff that actually matters for proxies, cross-border, and AI accounts.
80
+
81
+ ## Free API (no auth, CORS-enabled)
82
+
83
+ The CLI just calls IPOK's public API. You can too:
84
+
85
+ ```bash
86
+ curl "https://ipok.io/api/ip?ip=1.1.1.1" # full IP report (JSON)
87
+ curl "https://ipok.io/api/bgp?asn=AS13335&ip=1.1.1.1" # BGP upstreams/downstreams (RIPEstat)
88
+ curl "https://ipok.io/api/reverse-ip?ip=1.1.1.1" # domains hosted on the IP
89
+ ```
90
+
91
+ Docs: <https://ipok.io/developers>
92
+
93
+ ### Response shape (`/api/ip`, excerpt)
94
+
95
+ ```jsonc
96
+ {
97
+ "geo": { "ip", "version", "country", "city", "asn", "asName", "isp", "lat", "lon" },
98
+ "ipType": "residential | hosting | mobile",
99
+ "risk": 0,
100
+ "nativeType": "native | broadcast | unknown",
101
+ "scenarios": [{ "key": "tiktok", "stars": 3, "verdict": "try" }],
102
+ "services": [{ "key": "chatgpt", "status": "available" }],
103
+ "sources": [{ "source": "ip-api", "risk": 10, "flags": {} }],
104
+ "rdap": { "registry", "country", "registered", "org" }
105
+ }
106
+ ```
107
+
108
+ ## License
109
+
110
+ MIT — see [LICENSE](./LICENSE). Not affiliated with any provider; data is best-effort and for diagnostics only.
@@ -0,0 +1,41 @@
1
+ [build-system]
2
+ requires = ["hatchling"]
3
+ build-backend = "hatchling.build"
4
+
5
+ [project]
6
+ name = "ipok"
7
+ version = "0.1.0"
8
+ description = "Terminal IP purity / risk / AI-availability check — powered by ipok.io"
9
+ readme = "README.md"
10
+ requires-python = ">=3.8"
11
+ license = { text = "MIT" }
12
+ authors = [{ name = "ipok.io" }]
13
+ keywords = [
14
+ "ip", "ip-reputation", "ip-quality", "fraud", "risk-score",
15
+ "proxy-detection", "vpn-detection", "ip-purity", "geoip", "cli",
16
+ ]
17
+ classifiers = [
18
+ "Development Status :: 4 - Beta",
19
+ "Environment :: Console",
20
+ "Intended Audience :: Developers",
21
+ "Intended Audience :: System Administrators",
22
+ "License :: OSI Approved :: MIT License",
23
+ "Programming Language :: Python :: 3",
24
+ "Topic :: Internet",
25
+ "Topic :: Security",
26
+ "Topic :: System :: Networking",
27
+ ]
28
+ dependencies = []
29
+
30
+ [project.urls]
31
+ Homepage = "https://ipok.io"
32
+ Repository = "https://github.com/szp2005/ipok-cli"
33
+
34
+ [project.scripts]
35
+ ipok = "ipok.cli:main"
36
+
37
+ [tool.hatch.build.targets.wheel]
38
+ packages = ["src/ipok"]
39
+
40
+ [tool.hatch.build.targets.sdist]
41
+ include = ["src/ipok", "README.md", "LICENSE"]
@@ -0,0 +1,3 @@
1
+ from .cli import __version__, main
2
+
3
+ __all__ = ["__version__", "main"]
@@ -0,0 +1,4 @@
1
+ from .cli import main
2
+
3
+ if __name__ == "__main__":
4
+ raise SystemExit(main())
@@ -0,0 +1,167 @@
1
+ """IPOK CLI — terminal IP purity / risk / AI-availability check.
2
+
3
+ Powered by https://ipok.io (free, no-auth API). Zero third-party deps.
4
+ """
5
+ from __future__ import annotations
6
+
7
+ import json
8
+ import os
9
+ import sys
10
+ import urllib.error
11
+ import urllib.parse
12
+ import urllib.request
13
+
14
+ __version__ = "0.1.0"
15
+
16
+ API_DEFAULT = "https://ipok.io"
17
+ TIMEOUT = 25
18
+
19
+ # ---- ANSI helpers -----------------------------------------------------------
20
+ _NO_COLOR = bool(os.environ.get("NO_COLOR")) or not sys.stdout.isatty()
21
+
22
+
23
+ class C:
24
+ R = "" if _NO_COLOR else "\033[0m"
25
+ DIM = "" if _NO_COLOR else "\033[2m"
26
+ B = "" if _NO_COLOR else "\033[1m"
27
+ GREEN = "" if _NO_COLOR else "\033[32m"
28
+ YEL = "" if _NO_COLOR else "\033[33m"
29
+ RED = "" if _NO_COLOR else "\033[31m"
30
+ CYAN = "" if _NO_COLOR else "\033[36m"
31
+ GRAY = "" if _NO_COLOR else "\033[90m"
32
+
33
+
34
+ HELP = f"""IPOK CLI v{__version__} — IP purity / risk / AI-availability check (ipok.io)
35
+
36
+ USAGE:
37
+ ipok check this machine's egress IP
38
+ ipok <ip> check a specific IP (e.g. ipok 1.1.1.1)
39
+ ipok --json [ip] print raw JSON from the API
40
+ ipok -h, --help show this help
41
+ ipok -v, --version show version
42
+
43
+ ENV:
44
+ IPOK_API override API base (default https://ipok.io)
45
+ NO_COLOR disable colored output
46
+
47
+ Data by https://ipok.io — free, no API key required.
48
+ """
49
+
50
+
51
+ def fetch(ip: str | None, api: str) -> dict:
52
+ url = api.rstrip("/") + "/api/ip"
53
+ if ip:
54
+ url += "?" + urllib.parse.urlencode({"ip": ip})
55
+ req = urllib.request.Request(url, headers={"User-Agent": f"ipok-cli/{__version__}"})
56
+ with urllib.request.urlopen(req, timeout=TIMEOUT) as resp: # noqa: S310 (trusted host)
57
+ return json.load(resp)
58
+
59
+
60
+ def _band(risk: int) -> tuple[str, str]:
61
+ if risk < 15:
62
+ return C.GREEN, "Pristine"
63
+ if risk < 50:
64
+ return C.GREEN, "Clean"
65
+ if risk < 70:
66
+ return C.YEL, "Caution"
67
+ return C.RED, "High risk"
68
+
69
+
70
+ def render(d: dict) -> str:
71
+ g = d.get("geo", {}) or {}
72
+ risk = int(d.get("risk", 0) or 0)
73
+ bc, band = _band(risk)
74
+ out: list[str] = []
75
+
76
+ def row(k: str, v: str) -> None:
77
+ out.append(" " + C.GRAY + k.ljust(14) + C.R + " " + v)
78
+
79
+ out.append("")
80
+ out.append(" " + C.CYAN + "IPOK" + C.R + C.GRAY + " ip check " + C.R + C.DIM + "ipok.io" + C.R)
81
+ out.append(" " + C.GRAY + ("-" * 46) + C.R)
82
+ row("IP", C.B + str(g.get("ip", "-")) + C.R + C.GRAY + " IPv" + str(g.get("version", "?")) + C.R)
83
+ loc = " / ".join([x for x in [g.get("country"), g.get("city")] if x]) or "-"
84
+ row("Location", loc)
85
+ row("ASN", str(g.get("asn", "-")) + " " + str(g.get("asName") or g.get("isp") or ""))
86
+ row("Type", str(d.get("ipType", "-")) + C.GRAY + " native: " + str(d.get("nativeType", "-")) + C.R)
87
+ row("Risk", bc + str(risk) + "/100 " + band + C.R)
88
+
89
+ sig = d.get("signals") or []
90
+ if sig:
91
+ row("Signals", C.YEL + ", ".join(map(str, sig)) + C.R)
92
+
93
+ svc = d.get("services") or []
94
+ if svc:
95
+ parts = []
96
+ for s in svc:
97
+ st = s.get("status")
98
+ mark = (
99
+ C.GREEN + "OK" + C.R if st == "available"
100
+ else (C.RED + "NO" + C.R if st == "blocked" else C.GRAY + "?" + C.R)
101
+ )
102
+ parts.append(str(s.get("name")) + ":" + mark)
103
+ row("AI", " ".join(parts))
104
+
105
+ sc = d.get("scenarios") or []
106
+ if sc:
107
+ parts = []
108
+ for s in sc[:6]:
109
+ stars = "*" * int(s.get("stars", 0) or 0)
110
+ parts.append(str(s.get("key")) + " " + C.YEL + stars.ljust(5) + C.R)
111
+ row("Use-case", " ".join(parts))
112
+
113
+ srcs = [s for s in (d.get("sources") or []) if s.get("ok")]
114
+ if srcs:
115
+ row("Sources", C.DIM + ", ".join(
116
+ str(s.get("source")) + "=" + str(s.get("risk", "-")) for s in srcs) + C.R)
117
+
118
+ out.append(" " + C.GRAY + ("-" * 46) + C.R)
119
+ ipv = g.get("ip", "")
120
+ link = ("https://ipok.io/?ip=" + str(ipv)) if ipv else "https://ipok.io"
121
+ out.append(" " + C.CYAN + "full report: " + link + C.R)
122
+ out.append("")
123
+ return "\n".join(out)
124
+
125
+
126
+ def main(argv: list[str] | None = None) -> int:
127
+ args = list(sys.argv[1:] if argv is None else argv)
128
+ as_json = False
129
+ ip: str | None = None
130
+
131
+ for a in args:
132
+ if a in ("-h", "--help"):
133
+ print(HELP)
134
+ return 0
135
+ if a in ("-v", "--version"):
136
+ print(f"ipok {__version__}")
137
+ return 0
138
+ if a == "--json":
139
+ as_json = True
140
+ elif a.startswith("-"):
141
+ sys.stderr.write(f"ipok: unknown option {a}\n")
142
+ return 2
143
+ else:
144
+ ip = a
145
+
146
+ api = os.environ.get("IPOK_API", API_DEFAULT)
147
+ try:
148
+ data = fetch(ip, api)
149
+ except urllib.error.HTTPError as e:
150
+ sys.stderr.write(f"IPOK: request failed (HTTP {e.code})\n")
151
+ return 1
152
+ except (urllib.error.URLError, TimeoutError) as e:
153
+ sys.stderr.write(f"IPOK: request failed ({e})\n")
154
+ return 1
155
+ except Exception as e: # noqa: BLE001
156
+ sys.stderr.write(f"IPOK: {e}\n")
157
+ return 1
158
+
159
+ if as_json:
160
+ print(json.dumps(data, ensure_ascii=False, indent=2))
161
+ else:
162
+ print(render(data))
163
+ return 0
164
+
165
+
166
+ if __name__ == "__main__":
167
+ raise SystemExit(main())