linkshieldai 0.2.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.
@@ -0,0 +1,36 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ pull_request:
6
+
7
+ jobs:
8
+ test:
9
+ runs-on: ubuntu-latest
10
+ strategy:
11
+ fail-fast: false
12
+ matrix:
13
+ python-version: ["3.10", "3.11", "3.12"]
14
+ steps:
15
+ - uses: actions/checkout@v4
16
+ - uses: actions/setup-python@v5
17
+ with:
18
+ python-version: ${{ matrix.python-version }}
19
+ - name: Install package
20
+ run: python -m pip install -e ".[dev]"
21
+ - name: Run tests
22
+ run: python -m pytest
23
+
24
+ package:
25
+ runs-on: ubuntu-latest
26
+ steps:
27
+ - uses: actions/checkout@v4
28
+ - uses: actions/setup-python@v5
29
+ with:
30
+ python-version: "3.12"
31
+ - name: Install build tools
32
+ run: python -m pip install build twine
33
+ - name: Build package
34
+ run: python -m build
35
+ - name: Check package
36
+ run: python -m twine check dist/*
@@ -0,0 +1,11 @@
1
+ __pycache__/
2
+ *.py[cod]
3
+ .pytest_cache/
4
+ .ruff_cache/
5
+ .venv/
6
+ venv/
7
+ dist/
8
+ build/
9
+ *.egg-info/
10
+ .env
11
+ screenshot.png
@@ -0,0 +1,255 @@
1
+ Metadata-Version: 2.4
2
+ Name: linkshieldai
3
+ Version: 0.2.0
4
+ Summary: Python SDK for the LinkShieldAI URL safety API.
5
+ Project-URL: Homepage, https://linkshieldai.com
6
+ Project-URL: Documentation, https://docs.linkshieldai.com
7
+ Author: LinkShieldAI
8
+ License: MIT
9
+ Keywords: linkshieldai,phishing,sdk,security,url-safety
10
+ Classifier: Development Status :: 4 - Beta
11
+ Classifier: Intended Audience :: Developers
12
+ Classifier: License :: OSI Approved :: MIT License
13
+ Classifier: Programming Language :: Python :: 3
14
+ Classifier: Programming Language :: Python :: 3.10
15
+ Classifier: Programming Language :: Python :: 3.11
16
+ Classifier: Programming Language :: Python :: 3.12
17
+ Classifier: Topic :: Security
18
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
19
+ Requires-Python: >=3.10
20
+ Requires-Dist: httpx<1,>=0.27.0
21
+ Provides-Extra: dev
22
+ Requires-Dist: build>=1.2.0; extra == 'dev'
23
+ Requires-Dist: pytest-asyncio>=0.23.0; extra == 'dev'
24
+ Requires-Dist: pytest>=8.0.0; extra == 'dev'
25
+ Requires-Dist: twine>=5.0.0; extra == 'dev'
26
+ Description-Content-Type: text/markdown
27
+
28
+ # LinkShieldAI Python SDK
29
+
30
+ Python wrapper for the LinkShieldAI API at `https://api.linkshieldai.com`.
31
+
32
+ The SDK supports:
33
+
34
+ - Basic URL safety checks
35
+ - Detailed checks with screenshot URL and detected tag
36
+ - Screenshot download
37
+ - NSFW site checks
38
+ - Chimera AI classification
39
+ - Sync and async clients
40
+ - Retry/backoff for transient API failures
41
+ - A small command-line tool
42
+
43
+ ## Install
44
+
45
+ From this folder:
46
+
47
+ ```bash
48
+ python -m pip install -e .
49
+ ```
50
+
51
+ For tests:
52
+
53
+ ```bash
54
+ python -m pip install -e ".[dev]"
55
+ python -m pytest
56
+ ```
57
+
58
+ ## Authentication
59
+
60
+ The API uses a query parameter named `key`.
61
+
62
+ Pass the API key directly:
63
+
64
+ ```python
65
+ from linkshieldai import LinkShieldAI
66
+
67
+ client = LinkShieldAI(api_key="YOUR_API_KEY")
68
+ ```
69
+
70
+ Or set an environment variable:
71
+
72
+ ```powershell
73
+ $env:LINKSHIELDAI_API_KEY = "YOUR_API_KEY"
74
+ ```
75
+
76
+ ```python
77
+ from linkshieldai import LinkShieldAI
78
+
79
+ client = LinkShieldAI()
80
+ ```
81
+
82
+ ## Basic Check
83
+
84
+ Wraps:
85
+
86
+ ```text
87
+ GET https://api.linkshieldai.com/?key={key}&url={url}
88
+ ```
89
+
90
+ ```python
91
+ from linkshieldai import LinkShieldAI
92
+
93
+ client = LinkShieldAI()
94
+ result = client.basic_check("https://example.com")
95
+
96
+ print(result.result)
97
+ print(result.is_malicious)
98
+ print(result.raw)
99
+ ```
100
+
101
+ ## Detailed Check
102
+
103
+ Wraps:
104
+
105
+ ```text
106
+ GET https://api.linkshieldai.com/classify_link?key={key}&url={url}
107
+ ```
108
+
109
+ ```python
110
+ result = client.detailed_check("https://example.com")
111
+
112
+ print(result.result)
113
+ print(result.screenshot_url)
114
+ print(result.tag)
115
+ ```
116
+
117
+ The API field `"screenshot url"` is normalized to `screenshot_url`.
118
+
119
+ ## Download Screenshot
120
+
121
+ Wraps:
122
+
123
+ ```text
124
+ GET https://api.linkshieldai.com/screenshot/{file_name}
125
+ ```
126
+
127
+ ```python
128
+ image_bytes = client.get_screenshot("05046f.png")
129
+ client.get_screenshot("https://api.linkshieldai.com/screenshot/05046f.png", "site.png")
130
+ ```
131
+
132
+ ## NSFW Check
133
+
134
+ Wraps:
135
+
136
+ ```text
137
+ GET https://api.linkshieldai.com/nsfw/site?key={key}&url={url}
138
+ ```
139
+
140
+ ```python
141
+ result = client.nsfw_check("https://example.com")
142
+ print(result.is_nsfw)
143
+ ```
144
+
145
+ ## Chimera Check
146
+
147
+ Wraps:
148
+
149
+ ```text
150
+ GET https://api.linkshieldai.com/chimera?key={key}&url={url}
151
+ ```
152
+
153
+ ```python
154
+ result = client.chimera("https://google.com")
155
+
156
+ print(result.result)
157
+ print(result.probability)
158
+ print(result.detection_method)
159
+ print(result.matched_signatures)
160
+ ```
161
+
162
+ ## Async Usage
163
+
164
+ ```python
165
+ import asyncio
166
+ from linkshieldai import AsyncLinkShieldAI
167
+
168
+
169
+ async def main():
170
+ async with AsyncLinkShieldAI() as client:
171
+ result = await client.chimera("https://google.com")
172
+ print(result.result, result.probability)
173
+
174
+
175
+ asyncio.run(main())
176
+ ```
177
+
178
+ ## Custom API Host
179
+
180
+ The default host is:
181
+
182
+ ```text
183
+ https://api.linkshieldai.com
184
+ ```
185
+
186
+ You can override it for staging or testing:
187
+
188
+ ```python
189
+ client = LinkShieldAI(base_url="https://api.linkshieldai.com")
190
+ ```
191
+
192
+ ## Timeouts, Retries, and Logging
193
+
194
+ By default the SDK uses:
195
+
196
+ - `timeout=10.0`
197
+ - `max_retries=2`
198
+ - `backoff_factor=0.5`
199
+
200
+ Retries are applied to temporary connection failures and HTTP `429`, `502`, `503`, and `504`.
201
+
202
+ ```python
203
+ import logging
204
+ from linkshieldai import LinkShieldAI
205
+
206
+ logging.basicConfig(level=logging.DEBUG)
207
+
208
+ client = LinkShieldAI(
209
+ timeout=15.0,
210
+ max_retries=3,
211
+ backoff_factor=1.0,
212
+ )
213
+ ```
214
+
215
+ ## CLI
216
+
217
+ After installation, use:
218
+
219
+ ```bash
220
+ linkshieldai --api-key YOUR_API_KEY basic https://example.com
221
+ linkshieldai --api-key YOUR_API_KEY detailed https://example.com
222
+ linkshieldai --api-key YOUR_API_KEY nsfw https://example.com
223
+ linkshieldai --api-key YOUR_API_KEY chimera https://google.com
224
+ linkshieldai --api-key YOUR_API_KEY screenshot 05046f.png --output site.png
225
+ ```
226
+
227
+ You can omit `--api-key` if `LINKSHIELDAI_API_KEY` is set.
228
+
229
+ ## Errors
230
+
231
+ ```python
232
+ from linkshieldai import (
233
+ APIConnectionError,
234
+ APIResponseError,
235
+ APIStatusError,
236
+ AuthenticationError,
237
+ RateLimitError,
238
+ )
239
+ ```
240
+
241
+ - `AuthenticationError`: missing API key.
242
+ - `RateLimitError`: HTTP 429.
243
+ - `APIStatusError`: non-success HTTP status.
244
+ - `APIResponseError`: malformed JSON or API payload with `Error` / `error`.
245
+ - `APIConnectionError`: timeout, DNS, or connection failure.
246
+
247
+ Raw API payloads are preserved on result objects through `.raw`.
248
+
249
+ ## Production Notes
250
+
251
+ - Keep API keys server-side. Do not expose them in browser JavaScript.
252
+ - Use `max_retries` with a small non-zero value for bots, moderation pipelines, and web apps.
253
+ - Catch `RateLimitError` when running near the documented limits.
254
+ - Tests are mocked by default and do not call the live API.
255
+ - For live smoke tests, set `LINKSHIELDAI_API_KEY` and call the examples manually.
@@ -0,0 +1,228 @@
1
+ # LinkShieldAI Python SDK
2
+
3
+ Python wrapper for the LinkShieldAI API at `https://api.linkshieldai.com`.
4
+
5
+ The SDK supports:
6
+
7
+ - Basic URL safety checks
8
+ - Detailed checks with screenshot URL and detected tag
9
+ - Screenshot download
10
+ - NSFW site checks
11
+ - Chimera AI classification
12
+ - Sync and async clients
13
+ - Retry/backoff for transient API failures
14
+ - A small command-line tool
15
+
16
+ ## Install
17
+
18
+ From this folder:
19
+
20
+ ```bash
21
+ python -m pip install -e .
22
+ ```
23
+
24
+ For tests:
25
+
26
+ ```bash
27
+ python -m pip install -e ".[dev]"
28
+ python -m pytest
29
+ ```
30
+
31
+ ## Authentication
32
+
33
+ The API uses a query parameter named `key`.
34
+
35
+ Pass the API key directly:
36
+
37
+ ```python
38
+ from linkshieldai import LinkShieldAI
39
+
40
+ client = LinkShieldAI(api_key="YOUR_API_KEY")
41
+ ```
42
+
43
+ Or set an environment variable:
44
+
45
+ ```powershell
46
+ $env:LINKSHIELDAI_API_KEY = "YOUR_API_KEY"
47
+ ```
48
+
49
+ ```python
50
+ from linkshieldai import LinkShieldAI
51
+
52
+ client = LinkShieldAI()
53
+ ```
54
+
55
+ ## Basic Check
56
+
57
+ Wraps:
58
+
59
+ ```text
60
+ GET https://api.linkshieldai.com/?key={key}&url={url}
61
+ ```
62
+
63
+ ```python
64
+ from linkshieldai import LinkShieldAI
65
+
66
+ client = LinkShieldAI()
67
+ result = client.basic_check("https://example.com")
68
+
69
+ print(result.result)
70
+ print(result.is_malicious)
71
+ print(result.raw)
72
+ ```
73
+
74
+ ## Detailed Check
75
+
76
+ Wraps:
77
+
78
+ ```text
79
+ GET https://api.linkshieldai.com/classify_link?key={key}&url={url}
80
+ ```
81
+
82
+ ```python
83
+ result = client.detailed_check("https://example.com")
84
+
85
+ print(result.result)
86
+ print(result.screenshot_url)
87
+ print(result.tag)
88
+ ```
89
+
90
+ The API field `"screenshot url"` is normalized to `screenshot_url`.
91
+
92
+ ## Download Screenshot
93
+
94
+ Wraps:
95
+
96
+ ```text
97
+ GET https://api.linkshieldai.com/screenshot/{file_name}
98
+ ```
99
+
100
+ ```python
101
+ image_bytes = client.get_screenshot("05046f.png")
102
+ client.get_screenshot("https://api.linkshieldai.com/screenshot/05046f.png", "site.png")
103
+ ```
104
+
105
+ ## NSFW Check
106
+
107
+ Wraps:
108
+
109
+ ```text
110
+ GET https://api.linkshieldai.com/nsfw/site?key={key}&url={url}
111
+ ```
112
+
113
+ ```python
114
+ result = client.nsfw_check("https://example.com")
115
+ print(result.is_nsfw)
116
+ ```
117
+
118
+ ## Chimera Check
119
+
120
+ Wraps:
121
+
122
+ ```text
123
+ GET https://api.linkshieldai.com/chimera?key={key}&url={url}
124
+ ```
125
+
126
+ ```python
127
+ result = client.chimera("https://google.com")
128
+
129
+ print(result.result)
130
+ print(result.probability)
131
+ print(result.detection_method)
132
+ print(result.matched_signatures)
133
+ ```
134
+
135
+ ## Async Usage
136
+
137
+ ```python
138
+ import asyncio
139
+ from linkshieldai import AsyncLinkShieldAI
140
+
141
+
142
+ async def main():
143
+ async with AsyncLinkShieldAI() as client:
144
+ result = await client.chimera("https://google.com")
145
+ print(result.result, result.probability)
146
+
147
+
148
+ asyncio.run(main())
149
+ ```
150
+
151
+ ## Custom API Host
152
+
153
+ The default host is:
154
+
155
+ ```text
156
+ https://api.linkshieldai.com
157
+ ```
158
+
159
+ You can override it for staging or testing:
160
+
161
+ ```python
162
+ client = LinkShieldAI(base_url="https://api.linkshieldai.com")
163
+ ```
164
+
165
+ ## Timeouts, Retries, and Logging
166
+
167
+ By default the SDK uses:
168
+
169
+ - `timeout=10.0`
170
+ - `max_retries=2`
171
+ - `backoff_factor=0.5`
172
+
173
+ Retries are applied to temporary connection failures and HTTP `429`, `502`, `503`, and `504`.
174
+
175
+ ```python
176
+ import logging
177
+ from linkshieldai import LinkShieldAI
178
+
179
+ logging.basicConfig(level=logging.DEBUG)
180
+
181
+ client = LinkShieldAI(
182
+ timeout=15.0,
183
+ max_retries=3,
184
+ backoff_factor=1.0,
185
+ )
186
+ ```
187
+
188
+ ## CLI
189
+
190
+ After installation, use:
191
+
192
+ ```bash
193
+ linkshieldai --api-key YOUR_API_KEY basic https://example.com
194
+ linkshieldai --api-key YOUR_API_KEY detailed https://example.com
195
+ linkshieldai --api-key YOUR_API_KEY nsfw https://example.com
196
+ linkshieldai --api-key YOUR_API_KEY chimera https://google.com
197
+ linkshieldai --api-key YOUR_API_KEY screenshot 05046f.png --output site.png
198
+ ```
199
+
200
+ You can omit `--api-key` if `LINKSHIELDAI_API_KEY` is set.
201
+
202
+ ## Errors
203
+
204
+ ```python
205
+ from linkshieldai import (
206
+ APIConnectionError,
207
+ APIResponseError,
208
+ APIStatusError,
209
+ AuthenticationError,
210
+ RateLimitError,
211
+ )
212
+ ```
213
+
214
+ - `AuthenticationError`: missing API key.
215
+ - `RateLimitError`: HTTP 429.
216
+ - `APIStatusError`: non-success HTTP status.
217
+ - `APIResponseError`: malformed JSON or API payload with `Error` / `error`.
218
+ - `APIConnectionError`: timeout, DNS, or connection failure.
219
+
220
+ Raw API payloads are preserved on result objects through `.raw`.
221
+
222
+ ## Production Notes
223
+
224
+ - Keep API keys server-side. Do not expose them in browser JavaScript.
225
+ - Use `max_retries` with a small non-zero value for bots, moderation pipelines, and web apps.
226
+ - Catch `RateLimitError` when running near the documented limits.
227
+ - Tests are mocked by default and do not call the live API.
228
+ - For live smoke tests, set `LINKSHIELDAI_API_KEY` and call the examples manually.
@@ -0,0 +1,12 @@
1
+ import asyncio
2
+
3
+ from linkshieldai import AsyncLinkShieldAI
4
+
5
+
6
+ async def main():
7
+ async with AsyncLinkShieldAI() as client:
8
+ result = await client.chimera("https://google.com")
9
+ print(result.result, result.probability)
10
+
11
+
12
+ asyncio.run(main())
@@ -0,0 +1,8 @@
1
+ from linkshieldai import LinkShieldAI
2
+
3
+
4
+ client = LinkShieldAI(api_key="test-key")
5
+ result = client.basic_check("https://example.com")
6
+
7
+ print(result.result)
8
+ print("malicious:", result.is_malicious)
@@ -0,0 +1,9 @@
1
+ from linkshieldai import LinkShieldAI
2
+
3
+
4
+ client = LinkShieldAI(api_key="test-key")
5
+ result = client.chimera("https://google.com")
6
+
7
+ print("result:", result.result)
8
+ print("probability:", result.probability)
9
+ print("method:", result.detection_method)
@@ -0,0 +1,13 @@
1
+ from linkshieldai import LinkShieldAI
2
+
3
+
4
+ client = LinkShieldAI(api_key="test-key")
5
+ result = client.detailed_check("https://example.com")
6
+
7
+ print("result:", result.result)
8
+ print("tag:", result.tag)
9
+ print("screenshot:", result.screenshot_url)
10
+
11
+ if result.screenshot_url:
12
+ client.get_screenshot(result.screenshot_url, "screenshot.png")
13
+ print("saved screenshot.png")
@@ -0,0 +1,7 @@
1
+ from linkshieldai import LinkShieldAI
2
+
3
+
4
+ client = LinkShieldAI(api_key="test-key")
5
+ result = client.nsfw_check("https://example.com")
6
+
7
+ print("nsfw:", result.is_nsfw)
@@ -0,0 +1,48 @@
1
+ [build-system]
2
+ requires = ["hatchling"]
3
+ build-backend = "hatchling.build"
4
+
5
+ [project]
6
+ name = "linkshieldai"
7
+ version = "0.2.0"
8
+ description = "Python SDK for the LinkShieldAI URL safety API."
9
+ readme = "README.md"
10
+ requires-python = ">=3.10"
11
+ license = { text = "MIT" }
12
+ authors = [
13
+ { name = "LinkShieldAI" }
14
+ ]
15
+ keywords = ["linkshieldai", "phishing", "url-safety", "security", "sdk"]
16
+ classifiers = [
17
+ "Development Status :: 4 - Beta",
18
+ "Intended Audience :: Developers",
19
+ "License :: OSI Approved :: MIT License",
20
+ "Programming Language :: Python :: 3",
21
+ "Programming Language :: Python :: 3.10",
22
+ "Programming Language :: Python :: 3.11",
23
+ "Programming Language :: Python :: 3.12",
24
+ "Topic :: Security",
25
+ "Topic :: Software Development :: Libraries :: Python Modules"
26
+ ]
27
+ dependencies = [
28
+ "httpx>=0.27.0,<1"
29
+ ]
30
+
31
+ [project.scripts]
32
+ linkshieldai = "linkshieldai.cli:main"
33
+
34
+ [project.optional-dependencies]
35
+ dev = [
36
+ "pytest>=8.0.0",
37
+ "pytest-asyncio>=0.23.0",
38
+ "build>=1.2.0",
39
+ "twine>=5.0.0"
40
+ ]
41
+
42
+ [project.urls]
43
+ Homepage = "https://linkshieldai.com"
44
+ Documentation = "https://docs.linkshieldai.com"
45
+
46
+ [tool.pytest.ini_options]
47
+ testpaths = ["tests"]
48
+ asyncio_mode = "auto"
@@ -0,0 +1,26 @@
1
+ from .async_client import AsyncLinkShieldAI
2
+ from .client import LinkShieldAI
3
+ from .errors import (
4
+ APIConnectionError,
5
+ APIResponseError,
6
+ APIStatusError,
7
+ AuthenticationError,
8
+ LinkShieldAIError,
9
+ RateLimitError,
10
+ )
11
+ from .types import BasicCheckResult, ChimeraResult, DetailedCheckResult, NSFWCheckResult
12
+
13
+ __all__ = [
14
+ "APIConnectionError",
15
+ "APIResponseError",
16
+ "APIStatusError",
17
+ "AsyncLinkShieldAI",
18
+ "AuthenticationError",
19
+ "BasicCheckResult",
20
+ "ChimeraResult",
21
+ "DetailedCheckResult",
22
+ "LinkShieldAI",
23
+ "LinkShieldAIError",
24
+ "NSFWCheckResult",
25
+ "RateLimitError",
26
+ ]