func (c *Client) parseMessage(rm router.Message) { var t struct { Type string `msgpack:"type"` ID string `msgpack:"id"` } err := msgpack.Unmarshal(rm.Payload, &t) if err != nil { return } id, err := utils.NewNodeIDFromString(t.ID) if err != nil { return } var m Message switch t.Type { case "chat": u := struct { Content ChatMessage `msgpack:"content"` }{} err := msgpack.Unmarshal(rm.Payload, &u) if err != nil { return } m = u.Content case "ack": u := struct { Content MessageAck `msgpack:"content"` }{} err := msgpack.Unmarshal(rm.Payload, &u) if err != nil { return } m = u.Content case "prof-res": u := struct { Content UserProfileResponse `msgpack:"content"` }{} err := msgpack.Unmarshal(rm.Payload, &u) if err != nil { return } m = u.Content c.Roster.Set(id, u.Content.Profile) case "prof-req": c.SendProfile(id) } if m != nil && t.Type != "ack" { c.mbuf.Push(readPair{M: m, ID: rm.Node}) if !bytes.Equal(rm.Node.NS[:], utils.GroupNamespace[:]) { c.sendAck(rm.Node, rm.ID) } } }
func (s *Session) commandLoop() { var chatID *utils.NodeID go func() { for { m, src, err := s.cli.Read() if err != nil { return } if msg, ok := m.(murcott.ChatMessage); ok { /* if chatID == nil { chatID = &src color.Printf("\n -> Start a chat with @{Wk} %s @{|}\n\n", src.String()) } */ str := src.String() color.Printf("\r* @{Wk}%s@{|} %s\n", str[len(str)-8:], msg.Text()) fmt.Print("* ") } } }() bio := bufio.NewReader(os.Stdin) for { if chatID == nil { fmt.Print("> ") } else { fmt.Print("* ") } line, _, err := bio.ReadLine() if err != nil { return } c := strings.Split(string(line), " ") if len(c) == 0 || c[0] == "" { continue } switch c[0] { case "/chat": if len(c) != 2 { color.Printf(" -> @{Rk}ERROR:@{|} /chat takes 1 argument\n") } else { nid, err := utils.NewNodeIDFromString(c[1]) if err != nil { color.Printf(" -> @{Rk}ERROR:@{|} invalid ID\n") } else { s.cli.Join(nid) chatID = &nid color.Printf(" -> Start a chat with @{Wk} %s @{|}\n\n", nid.String()) } } case "/add": if len(c) != 2 { color.Printf(" -> @{Rk}ERROR:@{|} /add takes 1 argument\n") } else { nid, err := utils.NewNodeIDFromString(c[1]) if err != nil { color.Printf(" -> @{Rk}ERROR:@{|} invalid ID\n") } else { s.cli.Roster.Set(nid, murcott.UserProfile{}) } } case "/mkg": key := utils.GeneratePrivateKey() id := utils.NewNodeID(utils.GroupNamespace, key.Digest()) color.Printf("Group ID: @{Wk} %s @{|}\n\n", id.String()) case "/stat": color.Printf(" * NumGoroutine() = %d\n", runtime.NumGoroutine()) nodes := s.cli.ActiveSessions() color.Printf(" * active sessions (%d) *\n", len(nodes)) for _, n := range nodes { color.Printf(" %v\n", n) } list := s.cli.Roster.List() color.Printf(" * Roster (%d) *\n", len(list)) for _, n := range list { color.Printf(" %v %s \n", n, s.cli.Roster.Get(n).Nickname) } case "/end": if chatID != nil { color.Printf(" -> End current chat\n") s.cli.Leave(*chatID) chatID = nil } case "/exit", "/quit": color.Printf(" -> See you@{Kg}.@{Kr}.@{Ky}.@{|}\n") return case "/help": showHelp() default: if chatID == nil { color.Printf(" -> @{Rk}ERROR:@{|} unknown command\n") showHelp() } else { s.cli.SendMessage(*chatID, murcott.NewPlainChatMessage(string(line))) } } } }