|
12 | 12 | """ |
13 | 13 |
|
14 | 14 | # pylint: disable=too-many-instance-attributes,too-few-public-methods,too-many-arguments |
| 15 | +import datetime |
15 | 16 | import ipaddress |
16 | 17 | from abc import ABCMeta |
17 | 18 | from collections.abc import Sequence |
18 | | -from typing import Optional, Union |
19 | 19 | from ipaddress import IPv4Address, IPv6Address |
| 20 | +from typing import Optional, Union |
20 | 21 |
|
21 | 22 | import geoip2.records |
22 | 23 | from geoip2._internal import Model |
@@ -512,6 +513,128 @@ def __init__( |
512 | 513 | self.is_tor_exit_node = is_tor_exit_node |
513 | 514 |
|
514 | 515 |
|
| 516 | +class AnonymousPlus(AnonymousIP): |
| 517 | + """Model class for the GeoIP Anonymous Plus. |
| 518 | +
|
| 519 | + This class provides the following attribute: |
| 520 | +
|
| 521 | + .. attribute: anonymizer_confidence |
| 522 | +
|
| 523 | + A score ranging from 1 to 99 that is our percent confidence that the |
| 524 | + network is currently part of an actively used VPN service. |
| 525 | +
|
| 526 | + :type: str |
| 527 | +
|
| 528 | + .. attribute:: is_anonymous |
| 529 | +
|
| 530 | + This is true if the IP address belongs to any sort of anonymous network. |
| 531 | +
|
| 532 | + :type: bool |
| 533 | +
|
| 534 | + .. attribute:: is_anonymous_vpn |
| 535 | +
|
| 536 | + This is true if the IP address is registered to an anonymous VPN |
| 537 | + provider. |
| 538 | +
|
| 539 | + If a VPN provider does not register subnets under names associated with |
| 540 | + them, we will likely only flag their IP ranges using the |
| 541 | + ``is_hosting_provider`` attribute. |
| 542 | +
|
| 543 | + :type: bool |
| 544 | +
|
| 545 | + .. attribute:: is_hosting_provider |
| 546 | +
|
| 547 | + This is true if the IP address belongs to a hosting or VPN provider |
| 548 | + (see description of ``is_anonymous_vpn`` attribute). |
| 549 | +
|
| 550 | + :type: bool |
| 551 | +
|
| 552 | + .. attribute:: is_public_proxy |
| 553 | +
|
| 554 | + This is true if the IP address belongs to a public proxy. |
| 555 | +
|
| 556 | + :type: bool |
| 557 | +
|
| 558 | + .. attribute:: is_residential_proxy |
| 559 | +
|
| 560 | + This is true if the IP address is on a suspected anonymizing network |
| 561 | + and belongs to a residential ISP. |
| 562 | +
|
| 563 | + :type: bool |
| 564 | +
|
| 565 | + .. attribute:: is_tor_exit_node |
| 566 | +
|
| 567 | + This is true if the IP address is a Tor exit node. |
| 568 | +
|
| 569 | + :type: bool |
| 570 | +
|
| 571 | + .. attribute:: ip_address |
| 572 | +
|
| 573 | + The IP address used in the lookup. |
| 574 | +
|
| 575 | + :type: ipaddress.IPv4Address or ipaddress.IPv6Address |
| 576 | +
|
| 577 | + .. attribute:: network |
| 578 | +
|
| 579 | + The network associated with the record. In particular, this is the |
| 580 | + largest network where all of the fields besides ip_address have the same |
| 581 | + value. |
| 582 | +
|
| 583 | + :type: ipaddress.IPv4Network or ipaddress.IPv6Network |
| 584 | +
|
| 585 | + .. attribute:: network_last_seen |
| 586 | +
|
| 587 | + The last day that the network was sighted in our analysis of anonymized |
| 588 | + networks. |
| 589 | +
|
| 590 | + :type: str |
| 591 | +
|
| 592 | + .. attribute:: provider_name |
| 593 | +
|
| 594 | + The name of the VPN provider (e.g., NordVPN, SurfShark, etc.) associated |
| 595 | + with the network. |
| 596 | +
|
| 597 | + :type: str |
| 598 | + """ |
| 599 | + |
| 600 | + anonymizer_confidence: Optional[int] |
| 601 | + network_last_seen: Optional[datetime.date] |
| 602 | + provider_name: Optional[str] |
| 603 | + |
| 604 | + def __init__( |
| 605 | + self, |
| 606 | + ip_address: IPAddress, |
| 607 | + *, |
| 608 | + anonymizer_confidence: Optional[int] = None, |
| 609 | + is_anonymous: bool = False, |
| 610 | + is_anonymous_vpn: bool = False, |
| 611 | + is_hosting_provider: bool = False, |
| 612 | + is_public_proxy: bool = False, |
| 613 | + is_residential_proxy: bool = False, |
| 614 | + is_tor_exit_node: bool = False, |
| 615 | + network: Optional[str] = None, |
| 616 | + network_last_seen: Optional[str] = None, |
| 617 | + prefix_len: Optional[int] = None, |
| 618 | + provider_name: Optional[str] = None, |
| 619 | + **_, |
| 620 | + ) -> None: |
| 621 | + super().__init__( |
| 622 | + is_anonymous=is_anonymous, |
| 623 | + is_anonymous_vpn=is_anonymous_vpn, |
| 624 | + is_hosting_provider=is_hosting_provider, |
| 625 | + is_public_proxy=is_public_proxy, |
| 626 | + is_residential_proxy=is_residential_proxy, |
| 627 | + is_tor_exit_node=is_tor_exit_node, |
| 628 | + ip_address=ip_address, |
| 629 | + network=network, |
| 630 | + prefix_len=prefix_len, |
| 631 | + ) |
| 632 | + self.anonymizer_confidence = anonymizer_confidence |
| 633 | + if network_last_seen is not None: |
| 634 | + self.network_last_seen = datetime.date.fromisoformat(network_last_seen) |
| 635 | + self.provider_name = provider_name |
| 636 | + |
| 637 | + |
515 | 638 | class ASN(SimpleModel): |
516 | 639 | """Model class for the GeoLite2 ASN. |
517 | 640 |
|
|
0 commit comments