package world import ( "fmt" "log" "slices" "git.chromaticdragon.app/pyrex/minimal-irc-server/v2/src/irc/users" "git.chromaticdragon.app/pyrex/minimal-irc-server/v2/src/transport" ) type World struct { Server *transport.Server UsersSystem *users.UsersSystem } type WrappedMessage struct { World *World Sender *users.User Content transport.Content } func NewWorld(server *transport.Server) *World { usersSystem := users.NewUsersSystem() return &World{ Server: server, UsersSystem: usersSystem, } } func (world *World) Wrap(msg transport.IncomingMessage) WrappedMessage { sender := world.UsersSystem.ByClientIdOrCreate(msg.Sender) return WrappedMessage{ World: world, Sender: sender, Content: msg.Content, } } // transmission of messages func (world *World) RelayToVagueDestination( msg WrappedMessage, name string, exclude []transport.ClientId, ) { nick, err := users.ValidateNick(name) if err == nil { // so it's a nick! world.RelayToNick(msg, nick, exclude) return } channel, err := users.ValidateChannelName(name) if err == nil { // so it's a channel! world.RelayToChannel(msg, channel, exclude) return } log.Fatalf("not sure how to send to %s", name) // TODO: Error response: "what is this?" } func (world *World) RelayToClient( msg WrappedMessage, client transport.ClientId, exclude []transport.ClientId, ) { content := createAnnotatedContent(msg) if slices.Contains(exclude, client) { return // don't relay } world.Server.SendMessage(client, content) } func (world *World) RelayToNick( msg WrappedMessage, nick users.Nick, exclude []transport.ClientId, ) { content := createAnnotatedContent(msg) user := world.UsersSystem.ByNick(nick) if user == nil { // TODO: Send an error reply. The user didn't exist return } if slices.Contains(exclude, user.GetClientId()) { return // don't relay } world.Server.SendMessage(user.GetClientId(), content) } func (world *World) RelayToChannel( msg WrappedMessage, channelName users.ChannelName, exclude []transport.ClientId, ) { content := createAnnotatedContent(msg) members := world.UsersSystem.ByChannel(channelName) log.Printf("Members of %s: %v\n", channelName, members) for member := range members { if slices.Contains(exclude, member.GetClientId()) { return // don't relay } world.Server.SendMessage(member.GetClientId(), content) } } func createAnnotatedContent( msg WrappedMessage, ) transport.Content { content := msg.Content fullSource := fmt.Sprintf("%s!clients/%d", msg.Sender.GetNick().Value, msg.Sender.GetClientId()) content.Source = &fullSource return content }