cloudcheck 11.2.0__cp315-cp315-win_amd64.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.
Files changed (70) hide show
  1. cloudcheck/__init__.py +3 -0
  2. cloudcheck/cloudcheck.cp315-win_amd64.pyd +0 -0
  3. cloudcheck/helpers.py +276 -0
  4. cloudcheck/providers/__init__.py +51 -0
  5. cloudcheck/providers/akamai.py +35 -0
  6. cloudcheck/providers/alibaba.py +13 -0
  7. cloudcheck/providers/amazon.py +50 -0
  8. cloudcheck/providers/arvancloud.py +22 -0
  9. cloudcheck/providers/backblaze.py +13 -0
  10. cloudcheck/providers/baidu.py +17 -0
  11. cloudcheck/providers/base.py +318 -0
  12. cloudcheck/providers/bunnycdn.py +13 -0
  13. cloudcheck/providers/cachefly.py +26 -0
  14. cloudcheck/providers/cdnetworks.py +14 -0
  15. cloudcheck/providers/cisco.py +41 -0
  16. cloudcheck/providers/cloudflare.py +42 -0
  17. cloudcheck/providers/cloudfront.py +20 -0
  18. cloudcheck/providers/ddosguard.py +14 -0
  19. cloudcheck/providers/dell.py +13 -0
  20. cloudcheck/providers/digitalocean.py +37 -0
  21. cloudcheck/providers/dod.py +31 -0
  22. cloudcheck/providers/fastly.py +24 -0
  23. cloudcheck/providers/fbi.py +18 -0
  24. cloudcheck/providers/gabia.py +13 -0
  25. cloudcheck/providers/gcore.py +27 -0
  26. cloudcheck/providers/github.py +30 -0
  27. cloudcheck/providers/gocache.py +19 -0
  28. cloudcheck/providers/google.py +66 -0
  29. cloudcheck/providers/heroku.py +9 -0
  30. cloudcheck/providers/hetzner.py +25 -0
  31. cloudcheck/providers/hostway.py +14 -0
  32. cloudcheck/providers/hpe.py +14 -0
  33. cloudcheck/providers/huawei.py +19 -0
  34. cloudcheck/providers/ibm.py +59 -0
  35. cloudcheck/providers/iboss.py +13 -0
  36. cloudcheck/providers/imperva.py +27 -0
  37. cloudcheck/providers/kamatera.py +19 -0
  38. cloudcheck/providers/kinx.py +15 -0
  39. cloudcheck/providers/ktcloud.py +15 -0
  40. cloudcheck/providers/leaseweb.py +32 -0
  41. cloudcheck/providers/lgtelecom.py +14 -0
  42. cloudcheck/providers/microsoft.py +48 -0
  43. cloudcheck/providers/microsoft365.py +33 -0
  44. cloudcheck/providers/navercloud.py +16 -0
  45. cloudcheck/providers/nhncloud.py +16 -0
  46. cloudcheck/providers/oracle.py +33 -0
  47. cloudcheck/providers/ovh.py +17 -0
  48. cloudcheck/providers/qrator.py +16 -0
  49. cloudcheck/providers/quiccloud.py +38 -0
  50. cloudcheck/providers/rackspace.py +23 -0
  51. cloudcheck/providers/ru_fso.py +13 -0
  52. cloudcheck/providers/salesforce.py +17 -0
  53. cloudcheck/providers/scaleway.py +17 -0
  54. cloudcheck/providers/skbroadband.py +14 -0
  55. cloudcheck/providers/stormwall.py +14 -0
  56. cloudcheck/providers/sucuri.py +14 -0
  57. cloudcheck/providers/tencent.py +17 -0
  58. cloudcheck/providers/uk_mod.py +16 -0
  59. cloudcheck/providers/upcloud.py +15 -0
  60. cloudcheck/providers/vultr.py +13 -0
  61. cloudcheck/providers/wasabi.py +17 -0
  62. cloudcheck/providers/x4b.py +14 -0
  63. cloudcheck/providers/yandex.py +107 -0
  64. cloudcheck/providers/zoho.py +27 -0
  65. cloudcheck/providers/zscaler.py +28 -0
  66. cloudcheck-11.2.0.dist-info/METADATA +336 -0
  67. cloudcheck-11.2.0.dist-info/RECORD +70 -0
  68. cloudcheck-11.2.0.dist-info/WHEEL +4 -0
  69. cloudcheck-11.2.0.dist-info/licenses/LICENSE +662 -0
  70. cloudcheck-11.2.0.dist-info/sboms/cloudcheck.cyclonedx.json +6703 -0
cloudcheck/__init__.py ADDED
@@ -0,0 +1,3 @@
1
+ from .cloudcheck import CloudCheck, CloudCheckError
2
+
3
+ __all__ = ["CloudCheck", "CloudCheckError"]
cloudcheck/helpers.py ADDED
@@ -0,0 +1,276 @@
1
+ import ipaddress
2
+ import os
3
+ import sys
4
+ from pathlib import Path
5
+ from typing import List, Set, Union
6
+
7
+ _warned_missing_api_key = False
8
+
9
+
10
+ def defrag_cidrs(
11
+ cidrs: List[Union[ipaddress.IPv4Network, ipaddress.IPv6Network]],
12
+ ) -> List[Union[ipaddress.IPv4Network, ipaddress.IPv6Network]]:
13
+ """
14
+ Defragment a list of CIDR blocks by merging adjacent networks.
15
+
16
+ Algorithm:
17
+ 1. Sort by network bits (prefix length)
18
+ 2. Iterate through pairs of adjacent networks
19
+ 3. If networks have equal network bits and can be merged into a larger network,
20
+ replace them with the merged network
21
+ 4. Repeat until no more merges are possible
22
+
23
+ Args:
24
+ cidrs: List of IPv4 or IPv6 network objects
25
+
26
+ Returns:
27
+ List of defragmented network objects
28
+ """
29
+ if not cidrs:
30
+ return []
31
+
32
+ # Convert to list and remove duplicates
33
+ networks = list(set(cidrs))
34
+
35
+ # Keep iterating until no more merges happen
36
+ changed = True
37
+ while changed:
38
+ changed = False
39
+
40
+ # Sort by network address
41
+ networks.sort(key=lambda x: (x.prefixlen, x.network_address.packed))
42
+
43
+ i = 0
44
+ while i < len(networks) - 1:
45
+ current = networks[i]
46
+ next_net = networks[i + 1]
47
+
48
+ # Check if we can merge these two networks
49
+ if _can_merge_networks(current, next_net):
50
+ # Create the merged network
51
+ merged = _merge_networks(current, next_net)
52
+
53
+ # Replace the two networks with the merged one
54
+ networks[i] = merged
55
+ networks.pop(i + 1)
56
+ changed = True
57
+ else:
58
+ i += 1
59
+
60
+ return networks
61
+
62
+
63
+ def _can_merge_networks(
64
+ net1: Union[ipaddress.IPv4Network, ipaddress.IPv6Network],
65
+ net2: Union[ipaddress.IPv4Network, ipaddress.IPv6Network],
66
+ ) -> bool:
67
+ """
68
+ Check if two networks can be merged into a larger network.
69
+
70
+ Two networks can be merged if:
71
+ 1. They have the same prefix length
72
+ 2. They are adjacent (one starts where the other ends)
73
+ 3. They can be combined into a network with prefix length - 1
74
+ """
75
+ # Must be same type (IPv4 or IPv6)
76
+ if net1.version != net2.version:
77
+ return False
78
+
79
+ # Must not be the same network
80
+ if net1 == net2:
81
+ return False
82
+
83
+ # Must have same prefix length
84
+ if net1.prefixlen != net2.prefixlen:
85
+ return False
86
+
87
+ # Must be adjacent networks
88
+ if not _are_adjacent_networks(net1, net2):
89
+ return False
90
+
91
+ return True
92
+
93
+
94
+ def _are_adjacent_networks(
95
+ net1: Union[ipaddress.IPv4Network, ipaddress.IPv6Network],
96
+ net2: Union[ipaddress.IPv4Network, ipaddress.IPv6Network],
97
+ ) -> bool:
98
+ """
99
+ Check if two networks are adjacent by creating two networks with sub-1 CIDR
100
+ and checking if they are equal.
101
+ """
102
+ # Must have same prefix length
103
+ if net1.prefixlen != net2.prefixlen:
104
+ return False
105
+
106
+ # Create two networks with sub-1 CIDR
107
+ new_prefixlen = net1.prefixlen - 1
108
+ if new_prefixlen < 0:
109
+ return False
110
+
111
+ # Create the two networks with the reduced prefix length using supernet
112
+ net1_parent = net1.supernet(prefixlen_diff=1)
113
+ net2_parent = net2.supernet(prefixlen_diff=1)
114
+
115
+ # If they are equal, the networks are adjacent
116
+ return net1_parent == net2_parent
117
+
118
+
119
+ def _merge_networks(
120
+ net1: Union[ipaddress.IPv4Network, ipaddress.IPv6Network],
121
+ net2: Union[ipaddress.IPv4Network, ipaddress.IPv6Network],
122
+ ) -> Union[ipaddress.IPv4Network, ipaddress.IPv6Network]:
123
+ """
124
+ Merge two adjacent networks into a larger network.
125
+ """
126
+ if net1 == net2:
127
+ raise ValueError("Networks must be different")
128
+
129
+ if not net1.version == net2.version:
130
+ raise ValueError("Networks must be the same version")
131
+
132
+ snet1 = net1.supernet(prefixlen_diff=1)
133
+ snet2 = net2.supernet(prefixlen_diff=1)
134
+ if not snet1 == snet2:
135
+ raise ValueError("Networks must be adjacent")
136
+
137
+ # Find the smaller network address
138
+ min_addr = min(net1.network_address, net2.network_address)
139
+
140
+ # Create the merged network with prefix length - 1
141
+ new_prefixlen = net1.prefixlen - 1
142
+ try:
143
+ return ipaddress.ip_network(f"{min_addr}/{new_prefixlen}")
144
+ except ValueError:
145
+ raise ValueError(
146
+ f"Failed to merge networks: {net1} (type: {type(net1)}) and {net2} (type: {type(net2)})"
147
+ )
148
+
149
+
150
+ def cidrs_to_strings(
151
+ cidrs: List[Union[ipaddress.IPv4Network, ipaddress.IPv6Network]],
152
+ ) -> List[str]:
153
+ """
154
+ Convert a list of network objects to string representations.
155
+
156
+ Args:
157
+ cidrs: List of network objects
158
+
159
+ Returns:
160
+ List of CIDR strings
161
+ """
162
+ return [str(cidr) for cidr in cidrs]
163
+
164
+
165
+ def strings_to_cidrs(
166
+ cidr_strings: List[str],
167
+ ) -> List[Union[ipaddress.IPv4Network, ipaddress.IPv6Network]]:
168
+ """
169
+ Convert a list of CIDR strings to network objects.
170
+
171
+ Args:
172
+ cidr_strings: List of CIDR strings
173
+
174
+ Returns:
175
+ List of network objects
176
+ """
177
+ networks = []
178
+ for cidr_str in cidr_strings:
179
+ try:
180
+ networks.append(ipaddress.ip_network(cidr_str, strict=False))
181
+ except ValueError:
182
+ # Skip invalid CIDR strings
183
+ continue
184
+ return networks
185
+
186
+
187
+ browser_base_headers = {
188
+ "accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7",
189
+ "accept-language": "en-US,en;q=0.9",
190
+ "cache-control": "no-cache",
191
+ "pragma": "no-cache",
192
+ "priority": "u=0, i",
193
+ "referer": "https://www.google.com/",
194
+ "sec-ch-ua": '"Chromium";v="127", "Not)A;Brand";v="99"',
195
+ "sec-ch-ua-mobile": "?0",
196
+ "sec-ch-ua-platform": '"Linux"',
197
+ "sec-fetch-dest": "document",
198
+ "sec-fetch-mode": "navigate",
199
+ "sec-fetch-site": "cross-site",
200
+ "sec-fetch-user": "?1",
201
+ "upgrade-insecure-requests": "1",
202
+ "user-agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36",
203
+ }
204
+
205
+
206
+ _client = None
207
+
208
+
209
+ def request(url, include_api_key=False, browser_headers=False, timeout=60, **kwargs):
210
+ import asyncio
211
+ import blasthttp
212
+
213
+ global _warned_missing_api_key, _client
214
+ if _client is None:
215
+ _client = blasthttp.BlastHTTP()
216
+ headers = kwargs.get("headers", {})
217
+ if browser_headers:
218
+ headers.update(browser_base_headers)
219
+ bbot_io_api_key = os.getenv("BBOT_IO_API_KEY")
220
+ if include_api_key:
221
+ if bbot_io_api_key:
222
+ headers["Authorization"] = f"Bearer {bbot_io_api_key}"
223
+ elif not _warned_missing_api_key:
224
+ _warned_missing_api_key = True
225
+ print(
226
+ "WARNING: BBOT_IO_API_KEY env var is not set; asndb requests will be "
227
+ "unauthenticated and may be rate-limited. Export BBOT_IO_API_KEY before "
228
+ "running the update.",
229
+ file=sys.stderr,
230
+ )
231
+ kwargs["headers"] = list(headers.items())
232
+ kwargs["timeout"] = timeout
233
+ kwargs.setdefault("follow_redirects", True)
234
+ kwargs.setdefault("verify_certs", True)
235
+
236
+ async def _send():
237
+ return await _client.request(url, **kwargs)
238
+
239
+ return asyncio.run(_send())
240
+
241
+
242
+ def parse_v2fly_domain_file(file_path: Path) -> Set[str]:
243
+ """Parse a domain list file and extract domains."""
244
+ print(f"Parsing {file_path}")
245
+ domains = set()
246
+ if not file_path.exists():
247
+ print(f"File {file_path} does not exist")
248
+ return domains
249
+
250
+ with open(file_path, "r", encoding="utf-8") as f:
251
+ for line in f:
252
+ line = line.strip()
253
+ # Handle inline comments by splitting on # and taking the first part
254
+ line = line.split("#")[0].strip()
255
+ if not line:
256
+ continue
257
+
258
+ if line.startswith("include:"):
259
+ include_file = line[8:]
260
+ include_path = file_path.parent / include_file
261
+ domains.update(parse_v2fly_domain_file(include_path))
262
+ continue
263
+
264
+ if line.startswith("domain:"):
265
+ domain = line[7:]
266
+ elif line.startswith("full:"):
267
+ domain = line[5:]
268
+ elif line.startswith("keyword:") or line.startswith("regexp:"):
269
+ continue
270
+ else:
271
+ domain = line
272
+
273
+ domain = domain.split("@")[0].strip()
274
+ if domain:
275
+ domains.add(domain.lower())
276
+ return domains
@@ -0,0 +1,51 @@
1
+ import importlib
2
+ from sys import stderr
3
+ from pathlib import Path
4
+ from typing import Dict, Type
5
+
6
+ from cloudcheck.providers.base import BaseProvider
7
+
8
+ # Dictionary to store loaded provider classes
9
+ _provider_classes: Dict[str, Type[BaseProvider]] = {}
10
+ _provider_instances: Dict[str, BaseProvider] = {}
11
+
12
+
13
+ def load_provider_classes() -> Dict[str, Type[BaseProvider]]:
14
+ """Dynamically load all cloud provider classes from the providers directory."""
15
+ global _provider_classes
16
+
17
+ if _provider_classes:
18
+ return _provider_classes
19
+
20
+ providers_path = Path(__file__).parent
21
+
22
+ for file in providers_path.glob("*.py"):
23
+ if file.stem in ("base", "__init__"):
24
+ continue
25
+
26
+ try:
27
+ import_path = f"cloudcheck.providers.{file.stem}"
28
+ module = importlib.import_module(import_path)
29
+
30
+ # Look for classes that inherit from BaseProvider
31
+ for attr_name in dir(module):
32
+ attr = getattr(module, attr_name)
33
+ if (
34
+ isinstance(attr, type)
35
+ and issubclass(attr, BaseProvider)
36
+ and attr != BaseProvider
37
+ ):
38
+ provider_name = attr.__name__
39
+ _provider_classes[provider_name] = attr
40
+
41
+ except Exception as e:
42
+ print(f"Failed to load provider from {file}: {e}", file=stderr)
43
+ raise
44
+
45
+ return _provider_classes
46
+
47
+
48
+ for provider_name, provider_class in load_provider_classes().items():
49
+ provider_instance = provider_class()
50
+ globals()[provider_name] = provider_instance
51
+ _provider_instances[provider_name] = provider_instance
@@ -0,0 +1,35 @@
1
+ import io
2
+ import zipfile
3
+ from cloudcheck.providers.base import BaseProvider
4
+ from typing import List
5
+
6
+
7
+ class Akamai(BaseProvider):
8
+ v2fly_company: str = "akamai"
9
+ tags: List[str] = ["cloud"]
10
+ short_description: str = "Akamai"
11
+ long_description: str = "A content delivery network and cloud services provider that delivers web and internet security services."
12
+ # {"org_id": "AKAMAI-ARIN", "org_name": "Akamai Technologies, Inc.", "country": "US", "asns": [12222,16625,16702,17204,17334,18680,18717,20189,22207,22452,23454,23455,26008,30675,31984,32787,33047,35993,35994,36029,36183,393234,393560]}
13
+ # {"org_id": "ORG-AT1-RIPE", "org_name": "Akamai International B.V.", "country": "NL", "asns": [20940,21342,21357,21399,31107,31108,31109,31110,31377,33905,34164,34850,35204,39836,43639,48163,49249,49846,200005,213120]}
14
+ # {"org_id": "ORG-ATI1-AP-APNIC", "org_name": "Akamai Technologies, Inc.", "country": "US", "asns": [23903,24319,45757,55409,55770,63949,133103]}
15
+ org_ids: List[str] = [
16
+ "AKAMAI-ARIN",
17
+ "ORG-AT1-RIPE",
18
+ "ORG-ATI1-AP-APNIC",
19
+ ]
20
+
21
+ _ips_url = "https://techdocs.akamai.com/property-manager/pdfs/akamai_ipv4_ipv6_CIDRs-txt.zip"
22
+
23
+ def fetch_cidrs(self):
24
+ response = self.request(self._ips_url)
25
+ ranges = set()
26
+ content = getattr(response, "content", b"")
27
+ # Extract the contents of the zip file to memory
28
+ with zipfile.ZipFile(io.BytesIO(content)) as zip_file:
29
+ for filename in ("akamai_ipv4_CIDRs.txt", "akamai_ipv6_CIDRs.txt"):
30
+ with zip_file.open(filename) as f:
31
+ for line in f.read().splitlines():
32
+ line = line.decode(errors="ignore").strip()
33
+ if line:
34
+ ranges.add(line)
35
+ return list(ranges)
@@ -0,0 +1,13 @@
1
+ from cloudcheck.providers.base import BaseProvider
2
+ from typing import List
3
+
4
+
5
+ class Alibaba(BaseProvider):
6
+ v2fly_company: str = "alibaba"
7
+ tags: List[str] = ["cloud"]
8
+ short_description: str = "Alibaba Cloud"
9
+ long_description: str = "A Chinese cloud computing company and subsidiary of Alibaba Group, providing cloud services and infrastructure."
10
+ # {"org_id": "ORG-ASEP1-AP-APNIC", "org_name": "Alibaba Cloud (Singapore) Private Limited", "country": "SG", "asns": [134963]}
11
+ org_ids: List[str] = [
12
+ "ORG-ASEP1-AP-APNIC",
13
+ ]
@@ -0,0 +1,50 @@
1
+ from cloudcheck.providers.base import BaseProvider
2
+ from typing import List, Dict
3
+
4
+
5
+ class Amazon(BaseProvider):
6
+ v2fly_company: str = "amazon"
7
+ short_description: str = "Amazon Web Services"
8
+ long_description: str = "A comprehensive cloud computing platform provided by Amazon, offering infrastructure services, storage, and computing power."
9
+ org_ids: List[str] = [
10
+ "AMAZO-139-ARIN", # Amazon.com, Inc., US
11
+ "AMAZO-141-ARIN", # Amazon Technologies, Inc., US
12
+ "AMAZO-22-ARIN", # Amazon Web Services, Inc., US
13
+ "AMAZO-4-ARIN", # Amazon.com, Inc., US
14
+ "AMAZON-4-ARIN", # Amazon.com, Inc., US
15
+ "ARL-76-ARIN", # Amazon Robotics LLC, US
16
+ "ASL-830-ARIN", # Amazon.com Services, LLC, US
17
+ "AT-9049-ARIN", # Amazon Technologies Inc., US
18
+ "AT-9066-ARIN", # Amazon Technologies Inc., US
19
+ "ORG-AARP1-AP-APNIC", # Amazon Asia-Pacific Resources Private Limited, SG
20
+ "ORG-ACSP2-AP-APNIC", # Amazon Corporate Services Pty Ltd, AU
21
+ "ORG-ACTS1-AP-APNIC", # Amazon Connection Technology Services (Beijing) Co., LTD, CN
22
+ "ORG-ADSI1-RIPE", # Amazon Data Services Ireland Ltd, IE
23
+ "ORG-ADSJ1-AP-APNIC", # Amazon Data Services Japan KK, JP
24
+ "ORG-AI2-AP-APNIC", # Amazon.com, Inc., US
25
+ ]
26
+ tags: List[str] = ["cloud"]
27
+ _bucket_name_regex = r"[a-z0-9_][a-z0-9-\.]{1,61}[a-z0-9]"
28
+ _region_regex = r"[a-z]{2}-[a-z]+-\d+"
29
+ regexes: Dict[str, List[str]] = {
30
+ "STORAGE_BUCKET_NAME": [r"(?P<name>" + _bucket_name_regex + r")"],
31
+ "STORAGE_BUCKET_HOSTNAME": [
32
+ r"(?P<name>" + _bucket_name_regex + r")\.s3\.amazonaws\.com",
33
+ r"(?P<name>"
34
+ + _bucket_name_regex
35
+ + r")\.s3-(?P<region>"
36
+ + _region_regex
37
+ + r")\.amazonaws\.com",
38
+ r"(?P<name>"
39
+ + _bucket_name_regex
40
+ + r")\.s3\.(?P<region>"
41
+ + _region_regex
42
+ + r")\.amazonaws\.com",
43
+ ],
44
+ }
45
+
46
+ _ips_url = "https://ip-ranges.amazonaws.com/ip-ranges.json"
47
+
48
+ def fetch_cidrs(self):
49
+ response = self.request(self._ips_url)
50
+ return list(set(p["ip_prefix"] for p in response.json()["prefixes"]))
@@ -0,0 +1,22 @@
1
+ from cloudcheck.providers.base import BaseProvider
2
+ from typing import List
3
+
4
+
5
+ class Arvancloud(BaseProvider):
6
+ domains: List[str] = ["arvancloud.ir"]
7
+ tags: List[str] = ["cdn"]
8
+ short_description: str = "Arvancloud"
9
+ long_description: str = "An Iranian cloud computing and content delivery network provider offering cloud infrastructure and CDN services."
10
+ # {"org_id": "ORG-AGTL2-RIPE", "org_name": "ARVANCLOUD GLOBAL TECHNOLOGIES L.L.C", "country": "AE", "asns": [57568,208006,210296]}
11
+ org_ids: List[str] = [
12
+ "ORG-AGTL2-RIPE",
13
+ ]
14
+
15
+ _ips_url = "https://www.arvancloud.ir/en/ips.txt"
16
+
17
+ def fetch_cidrs(self):
18
+ response = self.request(self._ips_url)
19
+ ranges = set()
20
+ if getattr(response, "status_code", 0) == 200:
21
+ ranges.update(response.text.splitlines())
22
+ return list(ranges)
@@ -0,0 +1,13 @@
1
+ from cloudcheck.providers.base import BaseProvider
2
+ from typing import List
3
+
4
+
5
+ class Backblaze(BaseProvider):
6
+ tags: List[str] = ["cloud"]
7
+ short_description: str = "Backblaze"
8
+ long_description: str = "A cloud storage and backup service provider offering data backup and cloud storage solutions."
9
+ # {"org_id": "BACKB-7-ARIN", "org_name": "Backblaze Inc", "country": "US", "asns": [40401,396865]}
10
+ org_ids: List[str] = [
11
+ "BACKB-7-ARIN",
12
+ ]
13
+ domains: List[str] = ["backblaze.com", "backblazeb2.com"]
@@ -0,0 +1,17 @@
1
+ from cloudcheck.providers.base import BaseProvider
2
+ from typing import List
3
+
4
+
5
+ class Baidu(BaseProvider):
6
+ v2fly_company: str = "baidu"
7
+ tags: List[str] = ["cdn"]
8
+ short_description: str = "Baidu Cloud Acceleration (百度云加速)"
9
+ long_description: str = "A Chinese content delivery network and cloud acceleration service provided by Baidu."
10
+ # {"org_id": "BUL-5-ARIN", "org_name": "Baidu USA LLC", "country": "US", "asns": [63288]}
11
+ # {"org_id": "ORG-BKL1-AP-APNIC", "org_name": "Baidu (Hong Kong) Limited", "country": "HK", "asns": [133746]}
12
+ # {"org_id": "ORG-BKL4-RIPE", "org_name": "Baidu (Hong Kong) Limited", "country": "HK", "asns": [199506]}
13
+ org_ids: List[str] = [
14
+ "BUL-5-ARIN",
15
+ "ORG-BKL1-AP-APNIC",
16
+ "ORG-BKL4-RIPE",
17
+ ]