package client import ( "errors" "io" "net" "time" "go.rctt.net/solec/core" ) type Handler interface { HandleMessage(msg core.Message) HandleError(err error) } type Client struct { h Handler conn net.Conn addr string uname string pass string } func NewClient(handler Handler, addr, uname, pass string) *Client { return &Client{ h: handler, addr: addr, uname: uname, pass: pass, } } func (c *Client) Connect() error { var err error c.conn, err = net.Dial("tcp", c.addr) if err != nil { return err } defer c.conn.Close() hs := core.Handshake{0, 1, core.ConnTypeUser} if err := core.Send(c.conn, hs); err != nil { return err } auth := core.UserAuth{c.uname, c.pass} if err := core.Send(c.conn, auth); err != nil { return err } c.read() return nil } func (c *Client) SendMessage(target, content string) error { msg := core.Message{ Source: c.uname + "@" + c.addr, Target: target, Content: content, } return core.Send(c.conn, msg) } func (c *Client) Join(channel string) error { umod := core.Usermode{ UserAddr: c.uname + "@" + c.addr, ChannelName: channel, Mode: core.UsermodeInChannel, } return core.Send(c.conn, umod) } func (c *Client) Leave(channel string) error { umod := core.Usermode{ UserAddr: c.uname + "@" + c.addr, ChannelName: channel, Mode: core.UsermodeNone, } return core.Send(c.conn, umod) } func (c *Client) GetHistory(channel string, since time.Time, count, offset int) error { hist := core.History{ Channel: channel, Since: since, Count: int64(count), Offset: int64(offset), } return core.Send(c.conn, hist) } func (c *Client) read() { for { payload, err := core.Read(c.conn) if err != nil { c.h.HandleError(err) if errors.Is(err, io.EOF) { break } } c.handlePayload(payload) } } func (c *Client) handlePayload(payload any) { switch v := payload.(type) { case core.Message: c.h.HandleMessage(v) } }