Implementation 1 of a minimalistic IRC server
This commit is contained in:
122
src/irc/world/world.go
Normal file
122
src/irc/world/world.go
Normal file
@@ -0,0 +1,122 @@
|
||||
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
|
||||
}
|
Reference in New Issue
Block a user