domaintools-api-test-upload 2.4.0__tar.gz → 2.4.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.
Files changed (41) hide show
  1. {domaintools_api_test_upload-2.4.0/domaintools_api_test_upload.egg-info → domaintools_api_test_upload-2.4.1}/PKG-INFO +2 -2
  2. domaintools_api_test_upload-2.4.1/VERSION +1 -0
  3. {domaintools_api_test_upload-2.4.0 → domaintools_api_test_upload-2.4.1}/domaintools/_version.py +1 -1
  4. {domaintools_api_test_upload-2.4.0 → domaintools_api_test_upload-2.4.1}/domaintools/api.py +142 -6
  5. {domaintools_api_test_upload-2.4.0 → domaintools_api_test_upload-2.4.1}/domaintools/cli/api.py +1 -0
  6. {domaintools_api_test_upload-2.4.0 → domaintools_api_test_upload-2.4.1}/domaintools/cli/commands/feeds.py +160 -0
  7. {domaintools_api_test_upload-2.4.0 → domaintools_api_test_upload-2.4.1}/domaintools/cli/constants.py +2 -0
  8. {domaintools_api_test_upload-2.4.0 → domaintools_api_test_upload-2.4.1}/domaintools/cli/utils.py +2 -0
  9. {domaintools_api_test_upload-2.4.0 → domaintools_api_test_upload-2.4.1}/domaintools/constants.py +4 -0
  10. {domaintools_api_test_upload-2.4.0 → domaintools_api_test_upload-2.4.1/domaintools_api_test_upload.egg-info}/PKG-INFO +2 -2
  11. {domaintools_api_test_upload-2.4.0 → domaintools_api_test_upload-2.4.1}/domaintools_api_test_upload.egg-info/requires.txt +1 -1
  12. {domaintools_api_test_upload-2.4.0 → domaintools_api_test_upload-2.4.1}/pyproject.toml +5 -1
  13. {domaintools_api_test_upload-2.4.0 → domaintools_api_test_upload-2.4.1}/tests/test_api.py +40 -0
  14. domaintools_api_test_upload-2.4.0/VERSION +0 -1
  15. {domaintools_api_test_upload-2.4.0 → domaintools_api_test_upload-2.4.1}/LICENSE +0 -0
  16. {domaintools_api_test_upload-2.4.0 → domaintools_api_test_upload-2.4.1}/README.md +0 -0
  17. {domaintools_api_test_upload-2.4.0 → domaintools_api_test_upload-2.4.1}/domaintools/__init__.py +0 -0
  18. {domaintools_api_test_upload-2.4.0 → domaintools_api_test_upload-2.4.1}/domaintools/base_results.py +0 -0
  19. {domaintools_api_test_upload-2.4.0 → domaintools_api_test_upload-2.4.1}/domaintools/cli/__init__.py +0 -0
  20. {domaintools_api_test_upload-2.4.0 → domaintools_api_test_upload-2.4.1}/domaintools/cli/commands/__init__.py +0 -0
  21. {domaintools_api_test_upload-2.4.0 → domaintools_api_test_upload-2.4.1}/domaintools/cli/commands/accounts.py +0 -0
  22. {domaintools_api_test_upload-2.4.0 → domaintools_api_test_upload-2.4.1}/domaintools/cli/commands/detects.py +0 -0
  23. {domaintools_api_test_upload-2.4.0 → domaintools_api_test_upload-2.4.1}/domaintools/cli/commands/domains.py +0 -0
  24. {domaintools_api_test_upload-2.4.0 → domaintools_api_test_upload-2.4.1}/domaintools/cli/commands/ips.py +0 -0
  25. {domaintools_api_test_upload-2.4.0 → domaintools_api_test_upload-2.4.1}/domaintools/cli/commands/iris.py +0 -0
  26. {domaintools_api_test_upload-2.4.0 → domaintools_api_test_upload-2.4.1}/domaintools/cli/main.py +0 -0
  27. {domaintools_api_test_upload-2.4.0 → domaintools_api_test_upload-2.4.1}/domaintools/exceptions.py +0 -0
  28. {domaintools_api_test_upload-2.4.0 → domaintools_api_test_upload-2.4.1}/domaintools/filters.py +0 -0
  29. {domaintools_api_test_upload-2.4.0 → domaintools_api_test_upload-2.4.1}/domaintools/results.py +0 -0
  30. {domaintools_api_test_upload-2.4.0 → domaintools_api_test_upload-2.4.1}/domaintools/utils.py +0 -0
  31. {domaintools_api_test_upload-2.4.0 → domaintools_api_test_upload-2.4.1}/domaintools_api_test_upload.egg-info/SOURCES.txt +0 -0
  32. {domaintools_api_test_upload-2.4.0 → domaintools_api_test_upload-2.4.1}/domaintools_api_test_upload.egg-info/dependency_links.txt +0 -0
  33. {domaintools_api_test_upload-2.4.0 → domaintools_api_test_upload-2.4.1}/domaintools_api_test_upload.egg-info/entry_points.txt +0 -0
  34. {domaintools_api_test_upload-2.4.0 → domaintools_api_test_upload-2.4.1}/domaintools_api_test_upload.egg-info/top_level.txt +0 -0
  35. {domaintools_api_test_upload-2.4.0 → domaintools_api_test_upload-2.4.1}/domaintools_async/__init__.py +0 -0
  36. {domaintools_api_test_upload-2.4.0 → domaintools_api_test_upload-2.4.1}/setup.cfg +0 -0
  37. {domaintools_api_test_upload-2.4.0 → domaintools_api_test_upload-2.4.1}/setup.py +0 -0
  38. {domaintools_api_test_upload-2.4.0 → domaintools_api_test_upload-2.4.1}/tests/test_async.py +0 -0
  39. {domaintools_api_test_upload-2.4.0 → domaintools_api_test_upload-2.4.1}/tests/test_cli.py +0 -0
  40. {domaintools_api_test_upload-2.4.0 → domaintools_api_test_upload-2.4.1}/tests/test_filters.py +0 -0
  41. {domaintools_api_test_upload-2.4.0 → domaintools_api_test_upload-2.4.1}/tests/test_utils.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: domaintools_api_test_upload
3
- Version: 2.4.0
3
+ Version: 2.4.1
4
4
  Summary: DomainTools Official Python API
5
5
  Author-email: DomainTools <integrations@domaintools.com>
6
6
  License: The MIT License (MIT)
@@ -40,7 +40,7 @@ Classifier: Topic :: Utilities
40
40
  Requires-Python: >=3.9
41
41
  Description-Content-Type: text/markdown
42
42
  License-File: LICENSE
43
- Requires-Dist: httpx
43
+ Requires-Dist: httpx==0.28.1
44
44
  Requires-Dist: rich
45
45
  Requires-Dist: typer
46
46
  Provides-Extra: test
@@ -0,0 +1 @@
1
+ 2.4.1
@@ -20,4 +20,4 @@ OTHER DEALINGS IN THE SOFTWARE.
20
20
 
21
21
  """
22
22
 
23
- current = "2.4.0"
23
+ current = "2.4.1"
@@ -94,7 +94,7 @@ class API(object):
94
94
 
95
95
  def _build_api_url(self, api_url=None, api_port=None):
96
96
  """Build the API url based on the given url and port. Defaults to `https://api.domaintools.com`"""
97
- rest_api_url = "https://api.domaintools.com"
97
+ rest_api_url = "https://api.domaintools.com.test"
98
98
  if api_url:
99
99
  rest_api_url = api_url
100
100
 
@@ -1033,7 +1033,21 @@ class API(object):
1033
1033
  )
1034
1034
 
1035
1035
  def nod(self, **kwargs) -> FeedsResults:
1036
- """Returns back list of the newly observed domains feed"""
1036
+ """Returns back list of the newly observed domains feed.
1037
+ Apex-level domains (e.g. example.com but not www.example.com) that we observe for the first time, and have not observed previously with our global DNS sensor network.
1038
+
1039
+ domain: str: Filter for an exact domain or a substring contained within a domain by prefixing or suffixing your substring with "*". Check the documentation for examples
1040
+
1041
+ before: str: Filter for records before the given time value inclusive or time offset relative to now
1042
+
1043
+ after: str: Filter for records after the given time value inclusive or time offset relative to now
1044
+
1045
+ headers: bool: Use in combination with Accept: text/csv headers to control if headers are sent or not
1046
+
1047
+ sessionID: str: A custom string to distinguish between different sessions
1048
+
1049
+ top: int: Limit the number of results to the top N, where N is the value of this parameter.
1050
+ """
1037
1051
  validate_feeds_parameters(kwargs)
1038
1052
  endpoint = kwargs.pop("endpoint", Endpoint.FEED.value)
1039
1053
  source = ENDPOINT_TO_SOURCE_MAP.get(endpoint)
@@ -1050,7 +1064,22 @@ class API(object):
1050
1064
  )
1051
1065
 
1052
1066
  def nad(self, **kwargs) -> FeedsResults:
1053
- """Returns back list of the newly active domains feed"""
1067
+ """Returns back list of the newly active domains feed. Contains domains that have been observed after having not been seen for at least 10 days in passive DNS.
1068
+ Apex-level domains (e.g. example.com but not www.example.com) that we observe based on the latest lifecycle of the domain. A domain may be seen either for the first time ever, or again after at least 10 days of inactivity (no observed resolutions in DNS).
1069
+ Populated with our global passive DNS (pDNS) sensor network.
1070
+
1071
+ domain: str: Filter for an exact domain or a substring contained within a domain by prefixing or suffixing your substring with "*". Check the documentation for examples
1072
+
1073
+ before: str: Filter for records before the given time value inclusive or time offset relative to now
1074
+
1075
+ after: str: Filter for records after the given time value inclusive or time offset relative to now
1076
+
1077
+ headers: bool: Use in combination with Accept: text/csv headers to control if headers are sent or not
1078
+
1079
+ sessionID: str: A custom string to distinguish between different sessions
1080
+
1081
+ top: int: Limit the number of results to the top N, where N is the value of this parameter.
1082
+ """
1054
1083
  validate_feeds_parameters(kwargs)
1055
1084
  endpoint = kwargs.pop("endpoint", Endpoint.FEED.value)
1056
1085
  source = ENDPOINT_TO_SOURCE_MAP.get(endpoint).value
@@ -1067,7 +1096,22 @@ class API(object):
1067
1096
  )
1068
1097
 
1069
1098
  def domainrdap(self, **kwargs) -> FeedsResults:
1070
- """Returns changes to global domain registration information, populated by the Registration Data Access Protocol (RDAP)"""
1099
+ """Returns changes to global domain registration information, populated by the Registration Data Access Protocol (RDAP).
1100
+ Compliments the 5-Minute WHOIS Feed as registries and registrars switch from Whois to RDAP.
1101
+ Contains parsed and raw RDAP-format domain registration data, emitted as soon as they are collected and parsed into a normalized structure.
1102
+
1103
+ domain: str: Filter for an exact domain or a substring contained within a domain by prefixing or suffixing your substring with "*". Check the documentation for examples
1104
+
1105
+ before: str: Filter for records before the given time value inclusive or time offset relative to now
1106
+
1107
+ after: str: Filter for records after the given time value inclusive or time offset relative to now
1108
+
1109
+ headers: bool: Use in combination with Accept: text/csv headers to control if headers are sent or not
1110
+
1111
+ sessionID: str: A custom string to distinguish between different sessions
1112
+
1113
+ top: int: Limit the number of results to the top N, where N is the value of this parameter.
1114
+ """
1071
1115
  validate_feeds_parameters(kwargs)
1072
1116
  endpoint = kwargs.pop("endpoint", Endpoint.FEED.value)
1073
1117
  source = ENDPOINT_TO_SOURCE_MAP.get(endpoint).value
@@ -1081,7 +1125,22 @@ class API(object):
1081
1125
  )
1082
1126
 
1083
1127
  def domaindiscovery(self, **kwargs) -> FeedsResults:
1084
- """Returns new domains as they are either discovered in domain registration information, observed by our global sensor network, or reported by trusted third parties"""
1128
+ """Returns new domains as they are either discovered in domain registration information, observed by our global sensor network, or reported by trusted third parties".
1129
+ Contains domains that are newly-discovered by Domain Tools in both passive and active DNS sources, emitted as soon as they are first observed.
1130
+ New domains as they are either discovered in domain registration information, observed by our global sensor network, or reported by trusted third parties.
1131
+
1132
+ domain: str: Filter for an exact domain or a substring contained within a domain by prefixing or suffixing your substring with "*". Check the documentation for examples
1133
+
1134
+ before: str: Filter for records before the given time value inclusive or time offset relative to now
1135
+
1136
+ after: str: Filter for records after the given time value inclusive or time offset relative to now
1137
+
1138
+ headers: bool: Use in combination with Accept: text/csv headers to control if headers are sent or not
1139
+
1140
+ sessionID: str: A custom string to distinguish between different sessions
1141
+
1142
+ top: int: Limit the number of results to the top N, where N is the value of this parameter.
1143
+ """
1085
1144
  validate_feeds_parameters(kwargs)
1086
1145
  endpoint = kwargs.pop("endpoint", Endpoint.FEED.value)
1087
1146
  source = ENDPOINT_TO_SOURCE_MAP.get(endpoint).value
@@ -1098,7 +1157,22 @@ class API(object):
1098
1157
  )
1099
1158
 
1100
1159
  def noh(self, **kwargs) -> FeedsResults:
1101
- """Returns back list of the newly observed hostnames feed"""
1160
+ """Returns back list of the newly observed hostnames feed.
1161
+ Contains fully qualified domain names (i.e. host names) that have never been seen before in passive DNS, emitted as soon as they are first observed.
1162
+ Hostname resolutions that we observe for the first time with our global DNS sensor network.
1163
+
1164
+ domain: str: Filter for an exact domain or a substring contained within a domain by prefixing or suffixing your substring with "*". Check the documentation for examples
1165
+
1166
+ before: str: Filter for records before the given time value inclusive or time offset relative to now
1167
+
1168
+ after: str: Filter for records after the given time value inclusive or time offset relative to now
1169
+
1170
+ headers: bool: Use in combination with Accept: text/csv headers to control if headers are sent or not
1171
+
1172
+ sessionID: str: A custom string to distinguish between different sessions
1173
+
1174
+ top: int: Limit the number of results to the top N, where N is the value of this parameter.
1175
+ """
1102
1176
  validate_feeds_parameters(kwargs)
1103
1177
  endpoint = kwargs.pop("endpoint", Endpoint.FEED.value)
1104
1178
  source = ENDPOINT_TO_SOURCE_MAP.get(endpoint).value
@@ -1113,3 +1187,65 @@ class API(object):
1113
1187
  cls=FeedsResults,
1114
1188
  **kwargs,
1115
1189
  )
1190
+
1191
+ def realtime_domain_risk(self, **kwargs) -> FeedsResults:
1192
+ """Returns back list of the realtime domain risk feed.
1193
+ Contains realtime domain risk information for apex-level domains, regardless of observed traffic.
1194
+
1195
+ domain: str: Filter for an exact domain or a substring contained within a domain by prefixing or suffixing your substring with "*". Check the documentation for examples
1196
+
1197
+ before: str: Filter for records before the given time value inclusive or time offset relative to now
1198
+
1199
+ after: str: Filter for records after the given time value inclusive or time offset relative to now
1200
+
1201
+ headers: bool: Use in combination with Accept: text/csv headers to control if headers are sent or not
1202
+
1203
+ sessionID: str: A custom string to distinguish between different sessions
1204
+
1205
+ top: int: Limit the number of results to the top N, where N is the value of this parameter.
1206
+ """
1207
+ validate_feeds_parameters(kwargs)
1208
+ endpoint = kwargs.pop("endpoint", Endpoint.FEED.value)
1209
+ source = ENDPOINT_TO_SOURCE_MAP.get(endpoint).value
1210
+ if endpoint == Endpoint.DOWNLOAD.value or kwargs.get("output_format", OutputFormat.JSONL.value) != OutputFormat.CSV.value:
1211
+ # headers param is allowed only in Feed API and CSV format
1212
+ kwargs.pop("headers", None)
1213
+
1214
+ return self._results(
1215
+ f"domain-risk-({source})",
1216
+ f"v1/{endpoint}/domainrisk/",
1217
+ response_path=(),
1218
+ cls=FeedsResults,
1219
+ **kwargs,
1220
+ )
1221
+
1222
+ def domainhotlist(self, **kwargs) -> FeedsResults:
1223
+ """Returns back list of domain hotlist feed.
1224
+ Contains high-risk, apex-level domains that are observed by DomainTools' global sensor network to be active within 24 hours.
1225
+
1226
+ domain: str: Filter for an exact domain or a substring contained within a domain by prefixing or suffixing your substring with "*". Check the documentation for examples
1227
+
1228
+ before: str: Filter for records before the given time value inclusive or time offset relative to now
1229
+
1230
+ after: str: Filter for records after the given time value inclusive or time offset relative to now
1231
+
1232
+ headers: bool: Use in combination with Accept: text/csv headers to control if headers are sent or not
1233
+
1234
+ sessionID: str: A custom string to distinguish between different sessions
1235
+
1236
+ top: int: Limit the number of results to the top N, where N is the value of this parameter.
1237
+ """
1238
+ validate_feeds_parameters(kwargs)
1239
+ endpoint = kwargs.pop("endpoint", Endpoint.FEED.value)
1240
+ source = ENDPOINT_TO_SOURCE_MAP.get(endpoint).value
1241
+ if endpoint == Endpoint.DOWNLOAD.value or kwargs.get("output_format", OutputFormat.JSONL.value) != OutputFormat.CSV.value:
1242
+ # headers param is allowed only in Feed API and CSV format
1243
+ kwargs.pop("headers", None)
1244
+
1245
+ return self._results(
1246
+ f"domain-hotlist-feed-({source})",
1247
+ f"v1/{endpoint}/domainhotlist/",
1248
+ response_path=(),
1249
+ cls=FeedsResults,
1250
+ **kwargs,
1251
+ )
@@ -214,6 +214,7 @@ class DTCLICommand:
214
214
  verify_ssl=verify_ssl,
215
215
  rate_limit=rate_limit,
216
216
  always_sign_api_key=always_sign_api_key,
217
+ api_url="https://api.domaintools.test",
217
218
  )
218
219
  dt_api_func = getattr(dt_api, name)
219
220
 
@@ -394,3 +394,163 @@ def feeds_noh(
394
394
  ),
395
395
  ):
396
396
  DTCLICommand.run(name=c.FEEDS_NOH, params=ctx.params)
397
+
398
+
399
+ @dt_cli.command(
400
+ name=c.FEEDS_DOMAINHOTLIST,
401
+ help=get_cli_helptext_by_name(command_name=c.FEEDS_DOMAINHOTLIST),
402
+ )
403
+ def feeds_domainhotlist(
404
+ ctx: typer.Context,
405
+ user: str = typer.Option(None, "-u", "--user", help="Domaintools API Username."),
406
+ key: str = typer.Option(None, "-k", "--key", help="DomainTools API key"),
407
+ creds_file: str = typer.Option(
408
+ "~/.dtapi",
409
+ "-c",
410
+ "--credfile",
411
+ help="Optional file with API username and API key, one per line.",
412
+ ),
413
+ no_verify_ssl: bool = typer.Option(
414
+ False,
415
+ "--no-verify-ssl",
416
+ help="Skip verification of SSL certificate when making HTTPs API calls",
417
+ ),
418
+ no_sign_api_key: bool = typer.Option(
419
+ False,
420
+ "--no-sign-api-key",
421
+ help="Skip signing of api key",
422
+ ),
423
+ header_authentication: bool = typer.Option(
424
+ True,
425
+ "--no-header-auth",
426
+ help="Don't use header authentication",
427
+ ),
428
+ output_format: str = typer.Option(
429
+ "jsonl",
430
+ "-f",
431
+ "--format",
432
+ help=f"Output format in [{OutputFormat.JSONL.value}, {OutputFormat.CSV.value}]",
433
+ callback=DTCLICommand.validate_feeds_format_input,
434
+ ),
435
+ endpoint: str = typer.Option(
436
+ Endpoint.FEED.value,
437
+ "-e",
438
+ "--endpoint",
439
+ help=f"Valid endpoints: [{Endpoint.FEED.value}, {Endpoint.DOWNLOAD.value}]",
440
+ callback=DTCLICommand.validate_endpoint_input,
441
+ ),
442
+ sessionID: str = typer.Option(
443
+ None,
444
+ "--session-id",
445
+ help="Unique identifier for the session",
446
+ ),
447
+ after: str = typer.Option(
448
+ None,
449
+ "--after",
450
+ help="Start of the time window, relative to the current time in seconds, for which data will be provided",
451
+ callback=DTCLICommand.validate_after_or_before_input,
452
+ ),
453
+ before: str = typer.Option(
454
+ None,
455
+ "--before",
456
+ help="The end of the query window in seconds, relative to the current time, inclusive",
457
+ callback=DTCLICommand.validate_after_or_before_input,
458
+ ),
459
+ domain: str = typer.Option(
460
+ None,
461
+ "-d",
462
+ "--domain",
463
+ help="A string value used to filter feed results",
464
+ ),
465
+ headers: bool = typer.Option(
466
+ False,
467
+ "--headers",
468
+ help="Adds a header to the first line of response when text/csv is set in header parameters",
469
+ ),
470
+ top: str = typer.Option(
471
+ None,
472
+ "--top",
473
+ help="Number of results to return in the response payload. This is ignored in download endpoint",
474
+ ),
475
+ ):
476
+ DTCLICommand.run(name=c.FEEDS_DOMAINHOTLIST, params=ctx.params)
477
+
478
+
479
+ @dt_cli.command(
480
+ name=c.FEEDS_REALTIME_DOMAIN_RISK,
481
+ help=get_cli_helptext_by_name(command_name=c.FEEDS_REALTIME_DOMAIN_RISK),
482
+ )
483
+ def feeds_realtime_domain_risk(
484
+ ctx: typer.Context,
485
+ user: str = typer.Option(None, "-u", "--user", help="Domaintools API Username."),
486
+ key: str = typer.Option(None, "-k", "--key", help="DomainTools API key"),
487
+ creds_file: str = typer.Option(
488
+ "~/.dtapi",
489
+ "-c",
490
+ "--credfile",
491
+ help="Optional file with API username and API key, one per line.",
492
+ ),
493
+ no_verify_ssl: bool = typer.Option(
494
+ False,
495
+ "--no-verify-ssl",
496
+ help="Skip verification of SSL certificate when making HTTPs API calls",
497
+ ),
498
+ no_sign_api_key: bool = typer.Option(
499
+ False,
500
+ "--no-sign-api-key",
501
+ help="Skip signing of api key",
502
+ ),
503
+ header_authentication: bool = typer.Option(
504
+ True,
505
+ "--no-header-auth",
506
+ help="Don't use header authentication",
507
+ ),
508
+ output_format: str = typer.Option(
509
+ "jsonl",
510
+ "-f",
511
+ "--format",
512
+ help=f"Output format in [{OutputFormat.JSONL.value}, {OutputFormat.CSV.value}]",
513
+ callback=DTCLICommand.validate_feeds_format_input,
514
+ ),
515
+ endpoint: str = typer.Option(
516
+ Endpoint.FEED.value,
517
+ "-e",
518
+ "--endpoint",
519
+ help=f"Valid endpoints: [{Endpoint.FEED.value}, {Endpoint.DOWNLOAD.value}]",
520
+ callback=DTCLICommand.validate_endpoint_input,
521
+ ),
522
+ sessionID: str = typer.Option(
523
+ None,
524
+ "--session-id",
525
+ help="Unique identifier for the session",
526
+ ),
527
+ after: str = typer.Option(
528
+ None,
529
+ "--after",
530
+ help="Start of the time window, relative to the current time in seconds, for which data will be provided",
531
+ callback=DTCLICommand.validate_after_or_before_input,
532
+ ),
533
+ before: str = typer.Option(
534
+ None,
535
+ "--before",
536
+ help="The end of the query window in seconds, relative to the current time, inclusive",
537
+ callback=DTCLICommand.validate_after_or_before_input,
538
+ ),
539
+ domain: str = typer.Option(
540
+ None,
541
+ "-d",
542
+ "--domain",
543
+ help="A string value used to filter feed results",
544
+ ),
545
+ headers: bool = typer.Option(
546
+ False,
547
+ "--headers",
548
+ help="Adds a header to the first line of response when text/csv is set in header parameters",
549
+ ),
550
+ top: str = typer.Option(
551
+ None,
552
+ "--top",
553
+ help="Number of results to return in the response payload. This is ignored in download endpoint",
554
+ ),
555
+ ):
556
+ DTCLICommand.run(name=c.FEEDS_REALTIME_DOMAIN_RISK, params=ctx.params)
@@ -43,5 +43,7 @@ IRIS_DETECT_IGNORED_DOMAINS = "iris_detect_ignored_domains"
43
43
  FEEDS_NAD = "nad"
44
44
  FEEDS_NOD = "nod"
45
45
  FEEDS_NOH = "noh"
46
+ FEEDS_DOMAINHOTLIST = "domainhotlist"
46
47
  FEEDS_DOMAINRDAP = "domainrdap"
47
48
  FEEDS_DOMAINDISCOVERY = "domaindiscovery"
49
+ FEEDS_REALTIME_DOMAIN_RISK = "realtime_domain_risk"
@@ -64,8 +64,10 @@ _command_help_mapper = {
64
64
  c.FEEDS_NAD: "Returns back newly active domains feed.",
65
65
  c.FEEDS_NOD: "Returns back newly observed domains feed.",
66
66
  c.FEEDS_NOH: "Returns back newly observed hosts feed.",
67
+ c.FEEDS_DOMAINHOTLIST: "Returns domaint hotlist feed.",
67
68
  c.FEEDS_DOMAINRDAP: "Returns changes to global domain registration information, populated by the Registration Data Access Protocol (RDAP).",
68
69
  c.FEEDS_DOMAINDISCOVERY: "Returns new domains as they are either discovered in domain registration information, observed by our global sensor network, or reported by trusted third parties.",
70
+ c.FEEDS_REALTIME_DOMAIN_RISK: "Returns realtime domain risk information for apex-level domains, regardless of observed traffic.",
69
71
  }
70
72
 
71
73
 
@@ -30,8 +30,12 @@ FEEDS_PRODUCTS_LIST = [
30
30
  "newly-observed-domains-feed-(s3)",
31
31
  "newly-observed-hosts-feed-(api)",
32
32
  "newly-observed-hosts-feed-(s3)",
33
+ "domain-hotlist-feed-(api)",
34
+ "domain-hotlist-feed-(s3)",
33
35
  "domain-registration-data-access-protocol-feed-(api)",
34
36
  "domain-registration-data-access-protocol-feed-(s3)",
37
+ "domain-risk-feed-(api)",
38
+ "domain-risk-feed-(s3)",
35
39
  "real-time-domain-discovery-feed-(api)",
36
40
  "real-time-domain-discovery-feed-(s3)",
37
41
  ]
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: domaintools_api_test_upload
3
- Version: 2.4.0
3
+ Version: 2.4.1
4
4
  Summary: DomainTools Official Python API
5
5
  Author-email: DomainTools <integrations@domaintools.com>
6
6
  License: The MIT License (MIT)
@@ -40,7 +40,7 @@ Classifier: Topic :: Utilities
40
40
  Requires-Python: >=3.9
41
41
  Description-Content-Type: text/markdown
42
42
  License-File: LICENSE
43
- Requires-Dist: httpx
43
+ Requires-Dist: httpx==0.28.1
44
44
  Requires-Dist: rich
45
45
  Requires-Dist: typer
46
46
  Provides-Extra: test
@@ -4,7 +4,11 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "domaintools_api_test_upload"
7
- dependencies = ["httpx", "rich", "typer"]
7
+ dependencies = [
8
+ "httpx==0.28.1",
9
+ "rich",
10
+ "typer"
11
+ ]
8
12
  requires-python = ">= 3.9"
9
13
  authors = [{ name = "DomainTools", email = "integrations@domaintools.com" }]
10
14
  description = "DomainTools Official Python API"
@@ -663,3 +663,43 @@ def test_feeds_endpoint_should_raise_error_if_asked_csv_format_for_download_api(
663
663
  feeds_api.domaindiscovery(after="-60", output_format="csv", endpoint="download")
664
664
 
665
665
  assert str(excinfo.value) == "csv format is not available in download API."
666
+
667
+
668
+ @vcr.use_cassette
669
+ def test_realtime_domain_risk():
670
+ results = feeds_api.realtime_domain_risk(after="-60", header_authentication=False)
671
+ for response in results.response():
672
+ assert results.status == 200
673
+
674
+ rows = response.strip().split("\n")
675
+ assert response is not None
676
+ assert len(rows) >= 1
677
+
678
+ for row in rows:
679
+ feed_result = json.loads(row)
680
+ assert "timestamp" in feed_result.keys()
681
+ assert "domain" in feed_result.keys()
682
+ assert "phishing_risk" in feed_result.keys()
683
+ assert "malware_risk" in feed_result.keys()
684
+ assert "proximity_risk" in feed_result.keys()
685
+ assert "overall_risk" in feed_result.keys()
686
+
687
+
688
+ @vcr.use_cassette
689
+ def test_domain_hotlist():
690
+ results = feeds_api.domainhotlist(after="-60", header_authentication=False)
691
+ for response in results.response():
692
+ assert results.status == 200
693
+
694
+ rows = response.strip().split("\n")
695
+ assert response is not None
696
+ assert len(rows) >= 1
697
+
698
+ for row in rows:
699
+ feed_result = json.loads(row)
700
+ assert "timestamp" in feed_result.keys()
701
+ assert "domain" in feed_result.keys()
702
+ assert "phishing_risk" in feed_result.keys()
703
+ assert "malware_risk" in feed_result.keys()
704
+ assert "proximity_risk" in feed_result.keys()
705
+ assert "overall_risk" in feed_result.keys()
@@ -1 +0,0 @@
1
- 2.4.0