AD-SearchAPI 1.0.3__tar.gz → 2.0.1__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,451 @@
1
+ Metadata-Version: 2.4
2
+ Name: AD-SearchAPI
3
+ Version: 2.0.1
4
+ Summary: A comprehensive Python client library for the Search API with enhanced error handling and balance management
5
+ Home-page: https://github.com/AntiChrist-Coder/search_api_library
6
+ Author: Search API Team
7
+ Author-email: support@search-api.dev
8
+ Project-URL: Bug Reports, https://github.com/AntiChrist-Coder/search_api_library/issues
9
+ Project-URL: Source, https://github.com/AntiChrist-Coder/search_api_library
10
+ Project-URL: Documentation, https://github.com/AntiChrist-Coder/search_api_library/blob/main/README.md
11
+ Keywords: search-api,email-search,phone-search,domain-search,people-search,api-client,balance-management,caching
12
+ Classifier: Development Status :: 5 - Production/Stable
13
+ Classifier: Intended Audience :: Developers
14
+ Classifier: License :: OSI Approved :: MIT License
15
+ Classifier: Programming Language :: Python :: 3
16
+ Classifier: Programming Language :: Python :: 3.8
17
+ Classifier: Programming Language :: Python :: 3.9
18
+ Classifier: Programming Language :: Python :: 3.10
19
+ Classifier: Programming Language :: Python :: 3.11
20
+ Classifier: Programming Language :: Python :: 3.12
21
+ Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content
22
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
23
+ Classifier: Topic :: Communications :: Email
24
+ Classifier: Topic :: Internet :: Name Service (DNS)
25
+ Requires-Python: >=3.8
26
+ Description-Content-Type: text/markdown
27
+ License-File: LICENSE
28
+ Requires-Dist: requests>=2.31.0
29
+ Requires-Dist: phonenumbers>=8.13.0
30
+ Requires-Dist: python-dateutil>=2.8.2
31
+ Requires-Dist: cachetools>=5.3.0
32
+ Requires-Dist: typing-extensions>=4.7.0
33
+ Requires-Dist: urllib3>=2.0.0
34
+ Provides-Extra: dev
35
+ Requires-Dist: pytest>=7.0.0; extra == "dev"
36
+ Requires-Dist: pytest-cov>=4.0.0; extra == "dev"
37
+ Requires-Dist: black>=23.0.0; extra == "dev"
38
+ Requires-Dist: flake8>=6.0.0; extra == "dev"
39
+ Requires-Dist: mypy>=1.0.0; extra == "dev"
40
+ Provides-Extra: brotli
41
+ Requires-Dist: brotli>=1.0.0; extra == "brotli"
42
+ Dynamic: author
43
+ Dynamic: author-email
44
+ Dynamic: classifier
45
+ Dynamic: description
46
+ Dynamic: description-content-type
47
+ Dynamic: home-page
48
+ Dynamic: keywords
49
+ Dynamic: license-file
50
+ Dynamic: project-url
51
+ Dynamic: provides-extra
52
+ Dynamic: requires-dist
53
+ Dynamic: requires-python
54
+ Dynamic: summary
55
+
56
+ # Search API Python Client v2.0
57
+
58
+ A comprehensive Python client library for the Search API with enhanced error handling, balance management, and improved data processing. Acquire your API key through @ADSearchEngine_bot on Telegram.
59
+
60
+ ## 🚀 New in v2.0
61
+
62
+ - **Enhanced Balance Management**: Manual balance checking capabilities
63
+ - **Access Logs Integration**: Retrieve and analyze API access logs
64
+ - **Improved Error Handling**: Comprehensive exception hierarchy with detailed error messages
65
+ - **Advanced Caching**: Configurable response caching with TTL
66
+ - **Better Data Models**: Enhanced data structures with metadata and cost tracking
67
+ - **Context Manager Support**: Automatic resource cleanup
68
+ - **Comprehensive Validation**: Input validation for all search types
69
+ - **Multiple Phone Formats**: Support for international, national, and E164 formats
70
+ - **Batch Operations**: Efficient handling of multiple searches
71
+ - **Debug Mode**: Detailed logging for troubleshooting
72
+ - **URL Encoding Fix**: Proper handling of phone numbers with + prefix
73
+ - **Response Parsing**: Robust handling of both list and dictionary API responses
74
+
75
+ ## 📦 Installation
76
+
77
+ ```bash
78
+ pip install AD-SearchAPI
79
+ ```
80
+
81
+ ## ⚡ Quick Start
82
+
83
+ ```python
84
+ from search_api import SearchAPI, InsufficientBalanceError
85
+
86
+ client = SearchAPI(api_key="your_api_key")
87
+
88
+ try:
89
+ balance = client.get_balance()
90
+ print(f"Current balance: {balance}")
91
+ print(f"Cost per search: ${balance.credit_cost_per_search}")
92
+
93
+ access_logs = client.get_access_logs()
94
+ print(f"Total access log entries: {len(access_logs)}")
95
+
96
+ result = client.search_email(
97
+ "example@domain.com",
98
+ include_house_value=True,
99
+ include_extra_info=True
100
+ )
101
+
102
+ print(f"Name: {result.person.name if result.person else 'N/A'}")
103
+ print(f"Total results: {result.total_results}")
104
+ print(f"Search cost: ${result.search_cost}")
105
+
106
+ for addr in result.addresses:
107
+ print(f"Address: {addr}")
108
+ if addr.zestimate:
109
+ print(f" Zestimate: ${addr.zestimate:,.2f}")
110
+
111
+ except InsufficientBalanceError as e:
112
+ print(f"Insufficient balance: {e}")
113
+ print(f"Current: {e.current_balance}, Required: {e.required_credits}")
114
+ ```
115
+
116
+ ## 🔧 Advanced Configuration
117
+
118
+ ```python
119
+ from search_api import SearchAPI, SearchAPIConfig
120
+
121
+ config = SearchAPIConfig(
122
+ api_key="your_api_key",
123
+ debug_mode=True, # Enable debug logging
124
+ enable_caching=True, # Enable response caching
125
+ cache_ttl=1800, # 30 minutes cache
126
+ max_cache_size=500, # Maximum cache entries
127
+ timeout=120, # 2 minutes timeout
128
+ max_retries=5, # Retry failed requests
129
+ proxy={ # Optional proxy
130
+ "http": "http://proxy:8080",
131
+ "https": "https://proxy:8080"
132
+ }
133
+ )
134
+
135
+ client = SearchAPI(config=config)
136
+ ```
137
+
138
+ ## 💰 Balance Management
139
+
140
+ The client provides balance checking capabilities, but does not automatically check balance before each search. You should check your balance manually when needed:
141
+
142
+ ```python
143
+ from search_api import InsufficientBalanceError
144
+
145
+ try:
146
+ balance = client.get_balance()
147
+ print(f"Balance: {balance.current_balance} {balance.currency}")
148
+ print(f"Cost per search: {balance.credit_cost_per_search}")
149
+
150
+ # Calculate required credits based on actual search costs
151
+ email_search_cost = 0.0025
152
+ phone_search_cost = 0.0025
153
+ domain_search_cost = 4.00
154
+
155
+ required_credits = 5 * email_search_cost
156
+ if balance.current_balance < required_credits:
157
+ print(f"⚠️ Insufficient balance for {required_credits} searches")
158
+ else:
159
+ print(f"✅ Sufficient balance for {required_credits} searches")
160
+
161
+ except InsufficientBalanceError as e:
162
+ print(f"❌ Insufficient balance: {e}")
163
+ print(f" Current: {e.current_balance}")
164
+ print(f" Required: {e.required_credits}")
165
+ ```
166
+
167
+ ## 💵 Pricing Information
168
+
169
+ ### Search Costs:
170
+ - **Email Search**: $0.0025 per search
171
+ - **Phone Search**: $0.0025 per search
172
+ - **Domain Search**: $4.00 per search
173
+
174
+ ### Optional Parameters:
175
+ - **House Value**: Additional $0.0005 per successful lookup
176
+ - **Extra Info**: Additional $0.0020 per successful lookup
177
+
178
+ ## 📊 Access Logs
179
+
180
+ Retrieve and analyze your API access logs:
181
+
182
+ ```python
183
+ # Get all access logs
184
+ access_logs = client.get_access_logs()
185
+
186
+ print(f"Total access log entries: {len(access_logs)}")
187
+
188
+ # Show recent activity
189
+ for log in access_logs[:5]:
190
+ print(f"IP: {log.ip_address}")
191
+ print(f"Last accessed: {log.last_accessed}")
192
+ print(f"Endpoint: {log.endpoint}")
193
+ print(f"Status: {log.status_code}")
194
+ print(f"Response time: {log.response_time:.3f}s")
195
+ print("---")
196
+
197
+ # Analyze access patterns
198
+ unique_ips = set(log.ip_address for log in access_logs)
199
+ print(f"Unique IP addresses: {len(unique_ips)}")
200
+
201
+ # Find most active IP
202
+ ip_counts = {}
203
+ for log in access_logs:
204
+ ip_counts[log.ip_address] = ip_counts.get(log.ip_address, 0) + 1
205
+
206
+ most_active_ip = max(ip_counts.items(), key=lambda x: x[1])
207
+ print(f"Most active IP: {most_active_ip[0]} ({most_active_ip[1]} accesses)")
208
+ ```
209
+
210
+ ## 🔍 Search Operations
211
+
212
+ ### Email Search
213
+
214
+ ```python
215
+ result = client.search_email(
216
+ "john.doe@example.com",
217
+ include_house_value=True,
218
+ include_extra_info=True,
219
+ phone_format="international" # or "national", "e164"
220
+ )
221
+
222
+ print(f"Email: {result.email}")
223
+ print(f"Valid: {result.email_valid}")
224
+ print(f"Type: {result.email_type}")
225
+ print(f"Search Cost: ${result.search_cost}")
226
+
227
+ if result.person:
228
+ print(f"Name: {result.person.name}")
229
+ print(f"DOB: {result.person.dob}")
230
+ print(f"Age: {result.person.age}")
231
+
232
+ for addr in result.addresses:
233
+ print(f"Address: {addr}")
234
+ if addr.zestimate:
235
+ print(f" Zestimate: ${addr.zestimate:,.2f}")
236
+
237
+ for phone in result.phone_numbers:
238
+ print(f"Phone: {phone.number}")
239
+ ```
240
+
241
+ ### Phone Search
242
+
243
+ ```python
244
+ results = client.search_phone(
245
+ "+1234567890",
246
+ include_house_value=True,
247
+ include_extra_info=True,
248
+ phone_format="international"
249
+ )
250
+
251
+ for result in results:
252
+ print(f"Phone: {result.phone.number}")
253
+ print(f"Search Cost: ${result.search_cost}")
254
+
255
+ if result.person:
256
+ print(f"Name: {result.person.name}")
257
+ print(f"DOB: {result.person.dob}")
258
+
259
+ print(f"Total results: {result.total_results}")
260
+ ```
261
+
262
+ ### Domain Search
263
+
264
+ ```python
265
+ result = client.search_domain("example.com")
266
+
267
+ print(f"Domain: {result.domain}")
268
+ print(f"Valid: {result.domain_valid}")
269
+ print(f"Total results: {result.total_results}")
270
+ print(f"Search Cost: ${result.search_cost}")
271
+
272
+ for email_result in result.results:
273
+ print(f"Email: {email_result.email}")
274
+ print(f"Valid: {email_result.email_valid}")
275
+ print(f"Type: {email_result.email_type}")
276
+
277
+ if email_result.person:
278
+ print(f"Name: {email_result.person.name}")
279
+ ```
280
+
281
+ ## 🛡️ Error Handling
282
+
283
+ The library provides comprehensive error handling with specific exception types:
284
+
285
+ ```python
286
+ from search_api import (
287
+ SearchAPIError,
288
+ AuthenticationError,
289
+ ValidationError,
290
+ InsufficientBalanceError,
291
+ RateLimitError,
292
+ ServerError,
293
+ NetworkError,
294
+ TimeoutError,
295
+ ConfigurationError
296
+ )
297
+
298
+ try:
299
+ result = client.search_email("test@example.com")
300
+ except ValidationError as e:
301
+ print(f"Invalid input: {e}")
302
+ except InsufficientBalanceError as e:
303
+ print(f"Insufficient balance: {e}")
304
+ print(f"Current: {e.current_balance}, Required: {e.required_credits}")
305
+ except AuthenticationError as e:
306
+ print(f"Authentication failed: {e}")
307
+ except RateLimitError as e:
308
+ print(f"Rate limit exceeded: {e}")
309
+ except ServerError as e:
310
+ print(f"Server error: {e}")
311
+ except NetworkError as e:
312
+ print(f"Network error: {e}")
313
+ except TimeoutError as e:
314
+ print(f"Request timeout: {e}")
315
+ except SearchAPIError as e:
316
+ print(f"API error: {e}")
317
+ ```
318
+
319
+ ## 🔄 Caching
320
+
321
+ The client supports configurable response caching:
322
+
323
+ ```python
324
+ # Enable caching with custom settings
325
+ config = SearchAPIConfig(
326
+ api_key="your_api_key",
327
+ enable_caching=True,
328
+ cache_ttl=3600, # 1 hour
329
+ max_cache_size=1000 # Maximum 1000 cached responses
330
+ )
331
+
332
+ client = SearchAPI(config=config)
333
+
334
+ # Cache is automatically used for repeated searches
335
+ result1 = client.search_email("test@example.com") # Cached
336
+ result2 = client.search_email("test@example.com") # From cache
337
+
338
+ # Clear cache when needed
339
+ client.clear_cache()
340
+ ```
341
+
342
+ ## 🧹 Context Manager
343
+
344
+ Use the client as a context manager for automatic resource cleanup:
345
+
346
+ ```python
347
+ with SearchAPI(api_key="your_api_key") as client:
348
+ balance = client.get_balance()
349
+ result = client.search_email("test@example.com")
350
+ # Resources automatically cleaned up when exiting context
351
+ ```
352
+
353
+ ## 📊 Data Models
354
+
355
+ ### Address Model
356
+
357
+ ```python
358
+ @dataclass
359
+ class Address:
360
+ street: str
361
+ city: Optional[str] = None
362
+ state: Optional[str] = None
363
+ postal_code: Optional[str] = None
364
+ country: Optional[str] = None
365
+ zestimate: Optional[Decimal] = None
366
+ zpid: Optional[str] = None
367
+ bedrooms: Optional[int] = None
368
+ bathrooms: Optional[float] = None
369
+ living_area: Optional[int] = None
370
+ home_status: Optional[str] = None
371
+ last_known_date: Optional[date] = None
372
+ ```
373
+
374
+ ### Person Model
375
+
376
+ ```python
377
+ @dataclass
378
+ class Person:
379
+ name: Optional[str] = None
380
+ dob: Optional[date] = None
381
+ age: Optional[int] = None
382
+ ```
383
+
384
+ ### PhoneNumber Model
385
+
386
+ ```python
387
+ @dataclass
388
+ class PhoneNumber:
389
+ number: str
390
+ country_code: str = "US"
391
+ is_valid: bool = True
392
+ phone_type: Optional[str] = None
393
+ carrier: Optional[str] = None
394
+ ```
395
+
396
+ ### BalanceInfo Model
397
+
398
+ ```python
399
+ @dataclass
400
+ class BalanceInfo:
401
+ current_balance: float
402
+ currency: str = "USD"
403
+ last_updated: Optional[datetime] = None
404
+ credit_cost_per_search: Optional[float] = None
405
+ ```
406
+
407
+ ### AccessLog Model
408
+
409
+ ```python
410
+ @dataclass
411
+ class AccessLog:
412
+ ip_address: str
413
+ last_accessed: Optional[datetime] = None
414
+ user_agent: Optional[str] = None
415
+ endpoint: Optional[str] = None
416
+ method: Optional[str] = None
417
+ status_code: Optional[int] = None
418
+ response_time: Optional[float] = None
419
+ ```
420
+
421
+ ## 🔧 Configuration Options
422
+
423
+ ### SearchAPIConfig
424
+
425
+ | Parameter | Type | Default | Description |
426
+ |-----------|------|---------|-------------|
427
+ | `api_key` | str | Required | Your API key |
428
+ | `base_url` | str | `"https://search-api.dev/search.php"` | API base URL |
429
+ | `max_retries` | int | `3` | Maximum retry attempts |
430
+ | `timeout` | int | `90` | Request timeout in seconds |
431
+ | `debug_mode` | bool | `False` | Enable debug logging |
432
+ | `enable_caching` | bool | `True` | Enable response caching |
433
+ | `cache_ttl` | int | `3600` | Cache time-to-live in seconds |
434
+ | `max_cache_size` | int | `1000` | Maximum cache entries |
435
+ | `proxy` | Dict | `None` | Proxy configuration |
436
+ | `user_agent` | str | Chrome UA | Custom user agent |
437
+
438
+ ## 📝 Examples
439
+
440
+ See the `examples/` directory for comprehensive usage examples:
441
+
442
+ - `basic_usage.py` - Basic search operations, balance checking, and access logs
443
+ - `advanced_usage.py` - Advanced features like caching, batch operations, and access log analysis
444
+
445
+ ## 🤝 Contributing
446
+
447
+ Contributions are welcome! Please submit a Pull Request with your changes or open an issue for discussion.
448
+
449
+ ## 📄 License
450
+
451
+ This project is licensed under the MIT License - see the LICENSE file for details.
@@ -0,0 +1,16 @@
1
+ requests>=2.31.0
2
+ phonenumbers>=8.13.0
3
+ python-dateutil>=2.8.2
4
+ cachetools>=5.3.0
5
+ typing-extensions>=4.7.0
6
+ urllib3>=2.0.0
7
+
8
+ [brotli]
9
+ brotli>=1.0.0
10
+
11
+ [dev]
12
+ pytest>=7.0.0
13
+ pytest-cov>=4.0.0
14
+ black>=23.0.0
15
+ flake8>=6.0.0
16
+ mypy>=1.0.0