package irc import ( "fmt" "log" "net" ) type Client struct { // communication conn net.Conn send chan<- Reply recv <-chan string // basic info username string realname string hostname string nick string serverPass bool registered bool // modes away bool invisible bool wallOps bool restricted bool operator bool localOperator bool // relations server *Server channels ChannelSet } type ClientSet map[*Client]bool func NewClient(server *Server, conn net.Conn) *Client { client := &Client{ channels: make(ChannelSet), conn: conn, hostname: LookupHostname(conn.RemoteAddr()), recv: StringReadChan(conn), server: server, } client.SetReplyToStringChan() return client } func (c *Client) SetReplyToStringChan() { send := make(chan Reply) write := StringWriteChan(c.conn) go func() { for reply := range send { replyStr := reply.String(c) log.Printf("%s <- %s", c.Id(), replyStr) write <- replyStr } }() c.send = send } // Adapt `chan string` to a `chan Message`. func (c *Client) Communicate() { for str := range c.recv { m, err := ParseMessage(str) if err != nil { // TODO handle error return } c.server.recv <- &ClientMessage{c, m} } } func (c *Client) Nick() string { if c.nick != "" { return c.nick } return "*" } func (c *Client) UModeString() string { mode := "+" if c.invisible { mode += "i" } if c.wallOps { mode += "w" } return mode } func (c *Client) HasNick() bool { return c.nick != "" } func (c *Client) HasUser() bool { return c.username != "" } func (c *Client) Username() string { if c.HasUser() { return c.username } return "*" } func (c *Client) UserHost() string { return fmt.Sprintf("%s!%s@%s", c.Nick(), c.Username(), c.hostname) } func (c *Client) Id() string { return c.UserHost() }