from collections import defaultdict from dataclasses import dataclass, field from typing import Dict, Set from paircd.client import Client from paircd.message import Message @dataclass class Channel: name: str topic: str = "" modes: Set[str] = field(default_factory=lambda: {"t"}) clients_by_nick: Dict[str, Client] = field(default_factory=dict) modes_by_nick: Dict[str, Set[str]] = field(default_factory=lambda: defaultdict(set)) def add_client(self, client: Client) -> None: self.clients_by_nick[client.nickname] = client if len(self.clients_by_nick) == 1: self.modes_by_nick[client.nickname].add("o") def remove_client_by_nick(self, nick: str) -> None: del self.clients_by_nick[nick] del self.modes_by_nick[nick] def write_message(self, msg: Message) -> None: for client in self.clients_by_nick.values(): # Don't broadcast client's messages back to themselves if msg.cmd == "PRIVMSG" and msg.prefix == client.id(): continue client.write_message(msg) def get_modes(self) -> Set[str]: return self.modes def get_mode_settings(self) -> str: return f"+{''.join(sorted(self.modes))}" def get_user_modes_by_nick(self, nick: str) -> Set[str]: return self.modes_by_nick[nick] def get_channel_name(self, nick: str) -> str: modes = self.get_user_modes_by_nick(nick) if "o" in modes: return f"@{nick}" if "v" in modes: return f"+{nick}" return nick def get_channel_size(self) -> int: return len(self.clients_by_nick) def rename_client(self, name: str, new_name: str) -> None: if name not in self.clients_by_nick: raise KeyError(f"No client on channel with nick {name}") if new_name in self.clients_by_nick: raise KeyError(f"Client already exists with nick {new_name}") self.clients_by_nick[new_name] = self.clients_by_nick[name] del self.clients_by_nick[name] self.modes_by_nick[new_name] = self.modes_by_nick[name] del self.modes_by_nick[name]