A Python port of the Invisible Internet Project (I2P)
at main 77 lines 2.3 kB view raw
1"""Addressbook manager for SusiDNS. 2 3Manages hostname-to-destination mappings with search, file I/O, 4and integration with the addressbook storage. 5 6Ported from i2p.susi.dns.AddressbookBean. 7""" 8 9from __future__ import annotations 10 11from dataclasses import dataclass 12from pathlib import Path 13 14 15@dataclass 16class AddressbookEntry: 17 """A single hostname→destination mapping.""" 18 hostname: str 19 destination: str 20 21 def __str__(self) -> str: 22 return f"{self.hostname}={self.destination}" 23 24 25class AddressbookManager: 26 """Manages .i2p hostname-to-destination mappings.""" 27 28 def __init__(self) -> None: 29 self._entries: dict[str, str] = {} 30 31 def add(self, hostname: str, destination: str) -> None: 32 """Add or update an entry.""" 33 self._entries[hostname] = destination 34 35 def remove(self, hostname: str) -> None: 36 """Remove an entry.""" 37 self._entries.pop(hostname, None) 38 39 def lookup(self, hostname: str) -> str | None: 40 """Look up a destination by hostname.""" 41 return self._entries.get(hostname) 42 43 def list_entries(self) -> list[AddressbookEntry]: 44 """List all entries sorted by hostname.""" 45 return [ 46 AddressbookEntry(h, d) 47 for h, d in sorted(self._entries.items()) 48 ] 49 50 def search(self, query: str) -> list[AddressbookEntry]: 51 """Search entries by hostname prefix.""" 52 query_lower = query.lower() 53 return [ 54 AddressbookEntry(h, d) 55 for h, d in sorted(self._entries.items()) 56 if query_lower in h.lower() 57 ] 58 59 def save(self, path: Path) -> None: 60 """Save entries to a hosts.txt file.""" 61 lines = [f"{h}={d}" for h, d in sorted(self._entries.items())] 62 path.write_text("\n".join(lines) + "\n") 63 64 @classmethod 65 def from_file(cls, path: Path) -> AddressbookManager: 66 """Load entries from a hosts.txt file.""" 67 mgr = cls() 68 if not path.exists(): 69 return mgr 70 for line in path.read_text().splitlines(): 71 line = line.strip() 72 if not line or line.startswith("#"): 73 continue 74 if "=" in line: 75 hostname, destination = line.split("=", 1) 76 mgr.add(hostname.strip(), destination.strip()) 77 return mgr