A Python port of the Invisible Internet Project (I2P)
1"""Addressbook — local hostname to destination database."""
2
3from __future__ import annotations
4
5import time
6from dataclasses import dataclass, field
7
8
9@dataclass
10class AddressbookEntry:
11 """A single hostname→destination mapping."""
12
13 hostname: str
14 destination: str # Base64-encoded Destination
15 added_at: float = field(default_factory=time.monotonic)
16 source: str = "local" # "local", "subscription", "manual"
17
18
19class Addressbook:
20 """Local hostname -> destination database."""
21
22 def __init__(self) -> None:
23 self._entries: dict[str, AddressbookEntry] = {} # lowercase hostname -> entry
24
25 def lookup(self, hostname: str) -> str | None:
26 """Look up destination for hostname. Case-insensitive."""
27 entry = self._entries.get(hostname.lower())
28 return entry.destination if entry is not None else None
29
30 def add_entry(self, hostname: str, destination: str, source: str = "local") -> None:
31 """Add or update an entry."""
32 key = hostname.lower()
33 self._entries[key] = AddressbookEntry(
34 hostname=key,
35 destination=destination,
36 source=source,
37 )
38
39 def remove_entry(self, hostname: str) -> bool:
40 """Remove entry. Returns True if existed."""
41 key = hostname.lower()
42 if key in self._entries:
43 del self._entries[key]
44 return True
45 return False
46
47 def has_entry(self, hostname: str) -> bool:
48 """Check if hostname exists in the addressbook."""
49 return hostname.lower() in self._entries
50
51 def list_all(self) -> dict[str, AddressbookEntry]:
52 """Return a copy of all entries."""
53 return dict(self._entries)
54
55 @property
56 def entry_count(self) -> int:
57 """Return the number of entries."""
58 return len(self._entries)