func cmdWho(source interface{}, params [][]byte) { c := source.(*Client) channame := string(params[0]) if channame[0] == '#' { channame = channame[1:] } var ch *core.Channel if ch = core.FindChannel("", channame); ch == nil { c.SendLineTo(nil, "403", "#%s :No such channel.", channame) return } // If the user isn't on the channel, don't let them check unless they // can view private channel data. if m := ch.GetMember(c.u); m == nil { if ok, err := perm.CheckChanViewData(me, c.u, ch, "members"); !ok { c.SendLineTo(nil, "482", "#%s :%s", ch.Name(), err) return } } it := ch.Users() c.WriteBlock(func() []byte { if it == nil { return nil } user := it.User() var prefixes string if user.Data("away") == "" { prefixes += "H" } else { prefixes += "G" } if user.Data("op") != "" { prefixes += "*" } prefixes += ChanModes.GetPrefixes(it) servername := core.Global.Data("name") result := fmt.Sprintf(":%s 352 %s #%s %s %s %s %s %s :0 %s\r\n", servername, c.u.Nick(), channame, user.GetIdent(), user.GetHostname(), servername, user.Nick(), prefixes, user.Data("realname")) it = it.ChanNext() return []byte(result) }) c.SendLineTo(nil, "315", "%s :End of /WHO list.", params[0]) }
func cmdNames(source interface{}, params [][]byte) { c := source.(*Client) channame := string(params[0]) if len(channame) > 0 && channame[0] == '#' { channame = channame[1:] } var ch *core.Channel if ch = core.FindChannel("", channame); ch == nil { c.SendLineTo(nil, "403", "#%s :No such channel.", channame) return } // If the user isn't on the channel, don't let them check unless they // can view private channel data. // Otherwise, get their prefixes. var myprefix string if m := ch.GetMember(c.u); m == nil { if ok, err := perm.CheckChanViewData(me, c.u, ch, "members"); !ok { c.SendLineTo(nil, "482", "#%s :%s", ch.Name(), err) return } myprefix = "=" } else { myprefix = ChanModes.GetPrefixes(m) } it := ch.Users() c.WriteBlock(func() []byte { if it == nil { return nil } names := fmt.Sprintf(":%s 353 %s %s #%s :", core.Global.Data("name"), c.u.Nick(), myprefix, channame) for ; it != nil; it = it.ChanNext() { name := ChanModes.GetPrefixes(it) + it.User().Nick() if len(names)+len(name) > 508 { break } names += " " + name } names += "\r\n" return []byte(names) }) c.SendLineTo(nil, "366", "#%s :End of /NAMES list", channame) }
func cmdOpflags(source interface{}, params [][]byte) { c := source.(*Client) channame := string(params[0]) if channame[0] == '#' { channame = channame[1:] } var ch *core.Channel if ch = core.FindChannel("", channame); ch == nil { c.SendLineTo(nil, "403", "#%s :No such channel.", channame) return } // If the user isn't on the channel, don't let them check unless they // can view private channel data. if m := ch.GetMember(c.u); m == nil { if ok, err := perm.CheckChanViewData(me, c.u, ch, "members"); !ok { c.SendLineTo(nil, "482", "#%s :%s", ch.Name(), err) return } } var target *core.User if target = core.GetUserByNick(string(params[1])); target == nil { c.SendLineTo(nil, "401", "%s :No such user.", params[1]) return } var m *core.Membership if m = ch.GetMember(target); m == nil { c.SendLineTo(nil, "304", ":OPFLAGS #%s: %s is not in the channel.", ch.Name(), target.Nick()) return } if ok, err := perm.CheckMemberViewData(me, c.u, m, "op"); !ok { c.SendLineTo(nil, "482", "#%s :%s: %s", ch.Name(), target.Nick(), err) return } var flags string if flags = m.Data("op"); flags == "" { c.SendLineTo(nil, "304", ":OPFLAGS #%s: %s has no channel op flags.", ch.Name(), target.Nick()) return } if flags == "on" { flags = perm.DefaultChanOp() } c.SendLineTo(nil, "304", ":OPFLAGS #%s: %s has channel op flags: %s", ch.Name(), target.Nick(), flags) }
func cmdMode(source interface{}, params [][]byte) { c := source.(*Client) // If we're viewing the modes of ourselves or a channel... if len(params) < 2 { if strings.ToUpper(c.u.Nick()) == strings.ToUpper(string(params[0])) { modeline := UserModes.GetModes(c.u) c.SendLineTo(nil, "221", ":+%s", modeline) return } if params[0][0] == '#' { channame := string(params[0][1:]) ch := core.FindChannel("", channame) if ch == nil { return } modeline := ChanModes.GetModes(ch) ts := ch.TS() c.SendLineTo(nil, "324", "#%s +%s", ch.Name(), modeline) c.SendLineTo(nil, "329", "#%s %d", ch.Name(), ts) return } return } // If we're listing list modes on a channel... if params[0][0] == '#' && params[1][0] != '+' && params[1][0] != '-' { channame := string(params[0][1:]) ch := core.FindChannel("", channame) if ch == nil { return } var badmodes string for _, mode := range string(params[1]) { name := ChanModes.GetName(mode) if name == "" { badmodes += string(mode) continue } if ok, err := perm.CheckChanViewData(me, c.u, ch, name); !ok { c.SendLineTo(nil, "482", "#%s :%s", ch.Name(), err) continue } // Different, fixed numerics for different // modes. Stupid protocol. num := "941" endnum := "940" switch mode { case 'b': num = "367" endnum = "368" case 'e': num = "348" endnum = "349" case 'I': num = "346" endnum = "347" } valid := ChanModes.ListMode(ch, int(mode), func(p, v string) { var setTime string = "0" var setBy string = core.Global.Data("name") words := strings.Fields(v) for _, word := range words { if len(word) > 6 && word[:6] == "setat-" { setTime = word[6:] continue } if len(word) > 6 && word[:6] == "setby-" { setBy = word[6:] continue } } c.SendLineTo(nil, num, "#%s %s %s %s", ch.Name(), p, setBy, setTime) }) if valid { c.SendLineTo(nil, endnum, "#%s :End of mode list.", ch.Name()) } else { badmodes += string(mode) } } if badmodes != "" { if badmodes != string(params[1]) { c.SendLineTo(nil, "501", "Unknown list modes: %s", badmodes) return } // If ALL the mode characters were invalid, we let it // fall through and try to treat it as setting modes. } else { return } } // If we're setting modes on ourselves... if strings.ToUpper(c.u.Nick()) == strings.ToUpper(string(params[0])) { var mpars []string if len(params) == 3 { mpars = strings.Fields(string(params[2])) } changes, err := UserModes.ParseModeLine(c.u, c.u, params[1], mpars) if err != nil { c.SendLineTo(nil, "501", "%s", err) } todo := make([]core.DataChange, 0, len(changes)) for _, cha := range changes { ok, err := perm.CheckUserData(me, c.u, c.u, cha.Name, cha.Data) if !ok { m := UserModes.GetMode(cha.Name) c.SendLineTo(nil, "482", "%s %c: %s", c.u.Nick(), m, err) continue } todo = append(todo, cha) } if len(todo) != 0 { c.u.SetDataList(me, c.u, todo) } return } if params[0][0] == '#' { channame := string(params[0][1:]) ch := core.FindChannel("", channame) if ch == nil { return } var mpars []string if len(params) == 3 { mpars = strings.Fields(string(params[2])) } changes, err := ChanModes.ParseModeLine(c.u, ch, params[1], mpars) if err != nil { c.SendLineTo(nil, "501", "%s", err) } todo := make([]core.DataChange, 0, len(changes)) for _, cha := range changes { if cha.Member != nil { ok, err := perm.CheckMemberData(me, c.u, cha.Member, cha.Name, cha.Data) if !ok { m := ChanModes.GetMode(cha.Name) c.SendLineTo(nil, "482", "#%s %c: %s", ch.Name(), m, err) continue } } else { ok, err := perm.CheckChanData(me, c.u, ch, cha.Name, cha.Data) if !ok { m := ChanModes.GetMode(cha.Name) c.SendLineTo(nil, "482", "#%s %c: %s", ch.Name(), m, err) continue } } todo = append(todo, cha) } if todo != nil { ch.SetDataList(me, c.u, todo) } return } c.SendLineTo(nil, "401", "%s %s :%s", c.u.Nick(), params[0], "No such nick or channel.") }