// GetModes gets the modeline associated with a user or channel. // It caches its result via metadata on the user, using the mode parser's // mode ID to disambiguate it from other mode parsers. func (p *ModeParser) GetModes(e core.Extensible) string { var modes string var params string for name, char := range p.nameToSimple { data := e.Data(name) if v, ok := p.getExt[char]; ok { data = v(e) } if data != "" { modes += string(char) } } for name, char := range p.nameToParametered { data := e.Data(name) if v, ok := p.getExt[char]; ok { data = v(e) } if data != "" { modes += string(char) params += " " + data } } return modes + params }
// HasOpFlag returns whether the user has the given op flag. // This both checks for the presence of the flag, and, if the flag is default, // the "on" keyword for default privileges. This function should not be used as // a direct means of determining a user's ability to do something; instead, // the appropriate permission check should be used, as this permits module to // hook the check on other conditions. It should be used IN said permission // hooks. // // If ch is non-nil, this is a channel op flag check and the user's membership // entry on the channel will be checked. If no such entry exists, the check // automatically fails. If ch is nil, this is a server op flag check, and the user's own metadata will be checked. func HasOpFlag(u *core.User, ch *core.Channel, flag string) bool { var e core.Extensible var defwords []string if ch == nil { e = u defwords = defServerOp } else { if m := ch.GetMember(u); m != nil { e = m } else { return false } defwords = defChanOp } words := strings.Fields(e.Data("op")) for _, word := range words { if word == flag { return true } if word == "on" { for _, defword := range defwords { if defword == flag { return true } } } } return false }
// Restricted returns whether the user is restricted by a restriction of the // given type on the given extensible. It handles checking for unrestriction // modes, as well as the given restriction being set. func Restricted(u *core.User, e core.Extensible, restrict string) bool { if e.Data("restrict "+restrict) != "" { if !banMatch(u, e, "unrestrict", restrict) { return true } } return false }
// ListMode calls the given function for every entry in the list mode, // with the parameter of this mode list entry, and its metadata value. If // there are none, it will not be called. func (p *ModeParser) ListMode(e core.Extensible, char int, f func(param, value string)) bool { prefix := p.list[char] if prefix != "" { e.DataRange(prefix+" ", func(name, value string) { if v, ok := p.nameToExt[prefix]; ok { _, addpar, _, _ := v(e, name, "", value) for _, par := range addpar { f(par, value) } } else { f(name[len(prefix)+1:], value) } }) return true } return false }
// banMatch returns whether the user has a ban on the given Extensible, // matching the given restriction, under the given prefix for ban types. // It handles checking for default bans, if this ban type is part of the // default. func banMatch(u *core.User, e core.Extensible, prefix, restrict string) (match bool) { def := defaultBan if prefix == "unrestrict" { def = defaultUnrestrict } defwords := strings.Fields(def) // Create matcher closure, to run for each ban. var reverse bool var prefixlen int var t string var hook func(u *core.User, mask string) bool matcher := func(name, value string) { words := strings.Fields(value) var found bool for _, word := range words { if word == restrict { found = true break } if word == "on" { var deffound bool for _, defword := range defwords { if defword == restrict { deffound = true break } } if deffound { found = true break } } } if !found { return } // If the hook returns true and we're NOT reversed, match. // If the hook returns false and we are reversed, match. if hook(u, name[prefixlen:]) == !reverse { match = true } } for t, hook = range banTypes { reverse = false prefixlen = len(prefix) + len(t) + 2 e.DataRange(prefix+" "+t+" ", matcher) if match == true { break } reverse = true prefixlen = len(prefix) + len(t) + 3 e.DataRange(prefix+" ~"+t+" ", matcher) if match == true { break } } return }