python ircd using asyncio
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

61 lines
2.1 KiB

2 years ago
2 years ago
  1. from collections import defaultdict
  2. from dataclasses import dataclass, field
  3. from typing import Dict, Set
  4. from paircd.client import Client
  5. from paircd.message import Message
  6. @dataclass
  7. class Channel:
  8. name: str
  9. topic: str = ""
  10. modes: Set[str] = field(default_factory=lambda: {"t"})
  11. clients_by_nick: Dict[str, Client] = field(default_factory=dict)
  12. modes_by_nick: Dict[str, Set[str]] = field(default_factory=lambda: defaultdict(set))
  13. def add_client(self, client: Client) -> None:
  14. self.clients_by_nick[client.nickname] = client
  15. if len(self.clients_by_nick) == 1:
  16. self.modes_by_nick[client.nickname].add("o")
  17. def remove_client_by_nick(self, nick: str) -> None:
  18. del self.clients_by_nick[nick]
  19. del self.modes_by_nick[nick]
  20. def write_message(self, msg: Message) -> None:
  21. for client in self.clients_by_nick.values():
  22. # Don't broadcast client's messages back to themselves
  23. if msg.cmd == "PRIVMSG" and msg.prefix == client.id():
  24. continue
  25. client.write_message(msg)
  26. def get_modes(self) -> Set[str]:
  27. return self.modes
  28. def get_mode_settings(self) -> str:
  29. return f"+{''.join(sorted(self.modes))}"
  30. def get_user_modes_by_nick(self, nick: str) -> Set[str]:
  31. return self.modes_by_nick[nick]
  32. def get_channel_name(self, nick: str) -> str:
  33. modes = self.get_user_modes_by_nick(nick)
  34. if "o" in modes:
  35. return f"@{nick}"
  36. if "v" in modes:
  37. return f"+{nick}"
  38. return nick
  39. def get_channel_size(self) -> int:
  40. return len(self.clients_by_nick)
  41. def rename_client(self, name: str, new_name: str) -> None:
  42. if name not in self.clients_by_nick:
  43. raise KeyError(f"No client on channel with nick {name}")
  44. if new_name in self.clients_by_nick:
  45. raise KeyError(f"Client already exists with nick {new_name}")
  46. self.clients_by_nick[new_name] = self.clients_by_nick[name]
  47. del self.clients_by_nick[name]
  48. self.modes_by_nick[new_name] = self.modes_by_nick[name]
  49. del self.modes_by_nick[name]