aeglis 1.0.0__py3-none-any.whl

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.
aeglis/__init__.py ADDED
@@ -0,0 +1,98 @@
1
+ import os
2
+ import json
3
+ import hmac
4
+ import hashlib
5
+ import requests
6
+
7
+ class AeglisError(Exception):
8
+ """Custom exception for Aeglis API errors"""
9
+ pass
10
+
11
+ class Aeglis:
12
+ def __init__(self, api_key: str):
13
+ """
14
+ Initialize the Aeglis SDK.
15
+ :param api_key: Your B2B API Key from the Aeglis Dashboard.
16
+ """
17
+ if not api_key:
18
+ raise ValueError("Aeglis Initialization Error: API key is required.")
19
+
20
+ self.api_key = api_key
21
+ self.base_url = "https://api.aeglis.com/v3/api"
22
+
23
+ # Use a session for connection pooling (faster subsequent requests)
24
+ self.session = requests.Session()
25
+ self.session.headers.update({
26
+ "Authorization": f"Bearer {self.api_key}"
27
+ })
28
+
29
+ def scan(self, input_text: str, end_user_id: str = "anonymous") -> dict:
30
+ """
31
+ 🛡️ QUICK SCAN (Synchronous)
32
+ Best for short text, URLs, and chat moderation.
33
+ """
34
+ if not input_text:
35
+ raise ValueError("Aeglis Error: input_text is required for Quick Scan.")
36
+
37
+ payload = {
38
+ "input_text": input_text,
39
+ "end_user_id": end_user_id
40
+ }
41
+
42
+ response = self.session.post(f"{self.base_url}/scan", json=payload)
43
+
44
+ if not response.ok:
45
+ raise AeglisError(f"API Error: {response.text}")
46
+
47
+ return response.json()
48
+
49
+ def deep_scan(self, file_path: str, input_text: str = "", end_user_id: str = "anonymous") -> dict:
50
+ """
51
+ 🔍 DEEP SCAN (Asynchronous File Scanning)
52
+ Triggers your configured Webhook upon completion.
53
+ """
54
+ if not os.path.exists(file_path):
55
+ raise FileNotFoundError(f"Aeglis Error: File not found at {file_path}")
56
+
57
+ # Using context manager to safely open and read the file
58
+ with open(file_path, "rb") as f:
59
+ files = {"file": f}
60
+
61
+ # Form data matches FastAPI Form(...) requirements
62
+ data = {}
63
+ if input_text:
64
+ data["input_text"] = input_text
65
+ if end_user_id:
66
+ data["end_user_id"] = end_user_id
67
+
68
+ response = self.session.post(f"{self.base_url}/deep-scan", files=files, data=data)
69
+
70
+ if not response.ok:
71
+ raise AeglisError(f"API Error: {response.text}")
72
+
73
+ return response.json()
74
+
75
+ def verify_webhook(self, raw_payload: bytes, signature_header: str, webhook_secret: str) -> dict:
76
+ """
77
+ ⚡ WEBHOOK VERIFICATION (Security)
78
+ Verifies the incoming HMAC SHA-256 signature to prevent spoofing.
79
+ """
80
+ if not raw_payload or not signature_header or not webhook_secret:
81
+ raise ValueError("Aeglis Webhook Error: Missing payload, signature, or secret.")
82
+
83
+ # Ensure payload is bytes (raw) for accurate hashing
84
+ if isinstance(raw_payload, str):
85
+ raw_payload = raw_payload.encode('utf-8')
86
+
87
+ secret_bytes = webhook_secret.encode('utf-8')
88
+
89
+ # Generate the signature using your 'v1=' standard
90
+ expected_hash = hmac.new(secret_bytes, raw_payload, hashlib.sha256).hexdigest()
91
+ expected_signature = f"v1={expected_hash}"
92
+
93
+ # Prevent Timing Attacks using compare_digest
94
+ if not hmac.compare_digest(expected_signature, signature_header):
95
+ raise AeglisError("Signature Mismatch: Possible spoofing attack blocked.")
96
+
97
+ # If safe, decode and return as a Python dictionary
98
+ return json.loads(raw_payload.decode('utf-8'))
@@ -0,0 +1,13 @@
1
+ Metadata-Version: 2.1
2
+ Name: aeglis
3
+ Version: 1.0.0
4
+ Summary: Official Python SDK for the Aeglis Security API
5
+ Home-page: https://developer.aeglis.com
6
+ Author: Aeglis Systems
7
+ Classifier: Programming Language :: Python :: 3
8
+ Classifier: License :: OSI Approved :: MIT License
9
+ Classifier: Operating System :: OS Independent
10
+ Requires-Python: >=3.7
11
+ Description-Content-Type: text/markdown
12
+ Requires-Dist: requests>=2.25.1
13
+
@@ -0,0 +1,5 @@
1
+ aeglis/__init__.py,sha256=zsVWruwDyyMXMfVFV__lh6zwbADY-6rX4L6qWbxYkJM,3755
2
+ aeglis-1.0.0.dist-info/METADATA,sha256=PkPmhvk72obVyaqJYYyoCToQMgHqbSHgOj5r7jBrzXQ,425
3
+ aeglis-1.0.0.dist-info/WHEEL,sha256=51RkbunBAw4BWsgaQWTpPhg4Diwp3c9P5iaLk67Hdtg,92
4
+ aeglis-1.0.0.dist-info/top_level.txt,sha256=V7u1B22gMCYbbt4JZK6_9RISYhUET4rT8-xPbNzH5ao,7
5
+ aeglis-1.0.0.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: bdist_wheel (0.47.0)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+
@@ -0,0 +1 @@
1
+ aeglis