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.
- linkshieldai-0.2.0/.github/workflows/ci.yml +36 -0
- linkshieldai-0.2.0/.gitignore +11 -0
- linkshieldai-0.2.0/PKG-INFO +255 -0
- linkshieldai-0.2.0/README.md +228 -0
- linkshieldai-0.2.0/examples/async_usage.py +12 -0
- linkshieldai-0.2.0/examples/basic_check.py +8 -0
- linkshieldai-0.2.0/examples/chimera_check.py +9 -0
- linkshieldai-0.2.0/examples/detailed_with_screenshot.py +13 -0
- linkshieldai-0.2.0/examples/nsfw_check.py +7 -0
- linkshieldai-0.2.0/pyproject.toml +48 -0
- linkshieldai-0.2.0/src/linkshieldai/__init__.py +26 -0
- linkshieldai-0.2.0/src/linkshieldai/_transport.py +76 -0
- linkshieldai-0.2.0/src/linkshieldai/_utils.py +122 -0
- linkshieldai-0.2.0/src/linkshieldai/async_client.py +113 -0
- linkshieldai-0.2.0/src/linkshieldai/cli.py +86 -0
- linkshieldai-0.2.0/src/linkshieldai/client.py +113 -0
- linkshieldai-0.2.0/src/linkshieldai/errors.py +57 -0
- linkshieldai-0.2.0/src/linkshieldai/types.py +42 -0
- linkshieldai-0.2.0/tests/test_async_client.py +59 -0
- linkshieldai-0.2.0/tests/test_cli.py +32 -0
- linkshieldai-0.2.0/tests/test_client.py +170 -0
- linkshieldai-0.2.0/tests/test_live_optional.py +17 -0
- linkshieldai-0.2.0/tests/test_main.py +34 -0
|
@@ -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,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,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,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
|
+
]
|