func addAccess(conn *irc.Conn, channel, nick, flags string) (string, string) { n := conn.GetNick(nick) if n == nil { return "", "" } section := conn.Network + " " + channel user := user(n) cflags, _ := auth.String(section, user) nflags := cflags for _, flag := range flags { if strings.IndexRune(cflags, flag) > -1 { // already has the flag continue } nflags += string(flag) } auth.AddOption(section, user, nflags) if updateAuth() != nil { say(conn, channel, "Error while writing to %s", authFile) } return user, nflags }
func removeAccess(conn *irc.Conn, channel, nick, flags string) (string, string) { n := conn.GetNick(nick) if n == nil { return "", "" } section := conn.Network + " " + channel user := user(n) cflags, _ := auth.String(section, user) nflags := "" for _, flag := range cflags { if strings.IndexRune(flags, flag) < 0 { // we're not removing this flag nflags += string(flag) } } auth.AddOption(section, user, nflags) if updateAuth() != nil { say(conn, channel, "Error while writing to %s", authFile) } return user, nflags }
func flags(conn *irc.Conn, nick *irc.Nick, args, target string) { channel, args := parseAccess(conn, nick, target, args, "") if channel == "" { return } query := strings.TrimSpace(args) if query == "" { query = nick.Nick } n := conn.GetNick(query) if n == nil { say(conn, target, "Could not find nick %s", query) return } user := user(n) if owner, _ := auth.String(conn.Network, "owner"); owner == user { say(conn, target, "%s is the owner", user) return } flags, _ := auth.String(conn.Network+" "+channel, user) if flags == "" { say(conn, target, "%s has no flags", user) } else { say(conn, target, "%s: %s", user, flags) } }
func ignore(conn *irc.Conn, nick *irc.Nick, args, target string) { channel, args := parseAccess(conn, nick, target, args, "a") if channel == "" { return } n := conn.GetNick(strings.TrimSpace(args)) if n == nil { say(conn, target, "Could not find nick %s", args) return } if nick == n { say(conn, target, "%s: you cannot ignore yourself", nick.Nick) } owner, _ := auth.String(conn.Network, "owner") if owner == user(n) { return } if addIgnore(conn, channel, n) { say(conn, target, "Ignoring %s", n.Host) } else { say(conn, target, "%s is already ignored", n.Host) } }
func unban(conn *irc.Conn, nick *irc.Nick, args, target string) { channel, args := parseAccess(conn, nick, target, args, "oh") if channel == "" || args == "" { return } ch := conn.GetChannel(channel) if ch == nil { say(conn, target, "%s: Unable to get channel information about %s", nick.Nick, channel) return } bans := strings.TrimSpace(args) split := strings.Fields(bans) for i, ban := range split { if strings.Index(ban, "@") != -1 { // it's already a host, do nothing continue } if b, ok := ch.Bans[ban]; ok { // we've seen this nick banned before split[i] = b } else if n := conn.GetNick(ban); n != nil { // the user is in one of our channels, here's our best guess split[i] = "*!*@" + n.Host } } bans = strings.Join(split, " ") modestring := "-" + strings.Repeat("b", len(bans)) + " " + bans conn.Mode(channel, modestring) }
func ban(conn *irc.Conn, nick *irc.Nick, args, target string) { channel, args := parseAccess(conn, nick, target, args, "oh") if channel == "" || args == "" { return } bans := strings.TrimSpace(args) split := strings.Fields(bans) // turn nicks into *!*@host for i, ban := range split { if strings.Index(ban, "@") != -1 { // already a host continue } n := conn.GetNick(ban) if n == nil { //couldn't find the nick, so just cross our fingers continue } split[i] = "*!*@" + n.Host } bans = strings.Join(split, " ") modestring := "+" + strings.Repeat("b", len(bans)) + " " + bans conn.Mode(channel, modestring) }
func handlePrivmsg(conn *irc.Conn, line *irc.Line) { nick := conn.GetNick(line.Nick) if nick == nil { return } nick.Host = line.Host if ignores[conn.Network][nick.Host] { return } defer func() { if r := recover(); r != nil { fmt.Println("Recovered from", r) callers := make([]uintptr, 10) runtime.Callers(4, callers) cutoff := runtime.FuncForPC(reflect.ValueOf(handlePrivmsg).Pointer()).Entry() for _, pc := range callers { function := runtime.FuncForPC(pc - 1) if function.Entry() == cutoff { break } file, line := function.FileLine(pc - 1) fmt.Printf("%s:%d\n\t%s\n", file, line, function.Name()) } } }() target := line.Args[0] if isChannel(target) { // message to a channel if !command(conn, nick, line.Args[1], target) { var video string if start := strings.Index(line.Args[1], "youtube.com/watch?"); start > -1 { start = strings.Index(line.Args[1], "v=") video = line.Args[1][start+2:] } if start := strings.Index(line.Args[1], "youtu.be/"); start > -1 { video = line.Args[1][start+9:] } if video != "" { if end := strings.IndexAny(video, " &#"); end > -1 { video = video[0:end] } youtube(conn, nick, video, target) } else { command(conn, nick, line.Args[1], target) } } } else if target == conn.Me.Nick { // message to us command(conn, nick, line.Args[1], line.Nick) } }
func removeIgnore(conn *irc.Conn, channel, nick string) (string, bool) { n := conn.GetNick(nick) if n == nil { return "", false } if _, ok := ignores[conn.Network][n.Host]; !ok { return n.Host, false } ignores[conn.Network][n.Host] = false, false auth.RemoveOption(conn.Network, n.Host) if updateAuth() != nil { say(conn, channel, "Error while writing to %s", authFile) } return n.Host, true }
func removeUser(conn *irc.Conn, channel, nick string) (string, bool) { n := conn.GetNick(nick) if n == nil { return "", false } section := conn.Network + " " + channel user := user(n) if !auth.RemoveOption(section, user) { return user, false } if updateAuth() != nil { say(conn, channel, "Error while writing to %s", authFile) } return user, true }
func kick(conn *irc.Conn, nick *irc.Nick, args, target string) { channel, args := parseAccess(conn, nick, target, args, "oh") if channel == "" || args == "" { return } split := strings.SplitN(args, " ", 2) if n := conn.GetNick(split[0]); n == nil || (split[0] != nick.Nick && (!hasAccess(conn, nick, channel, "o") && hasAccess(conn, n, channel, "oh"))) { // if we only have h, we can't kick people with o or h return } reason := "(" + nick.Nick + ")" if len(split) == 2 { reason += " " + split[1] } conn.Kick(channel, split[0], reason) }
func kickban(conn *irc.Conn, nick *irc.Nick, args, target string) { channel, args := parseAccess(conn, nick, target, args, "oh") if channel == "" || args == "" { return } split := strings.SplitN(args, " ", 2) n := conn.GetNick(split[0]) if n == nil || (split[0] != nick.Nick && (!hasAccess(conn, nick, channel, "o") && hasAccess(conn, n, channel, "oh"))) { return } conn.Mode(channel, "+b *!*@"+n.Host) reason := "(" + nick.Nick + ")" if len(split) == 2 { reason += " " + split[1] } conn.Kick(channel, split[0], reason) }
func handleJoin(conn *irc.Conn, line *irc.Line) { // autovoice users with v flag if line.Nick == conn.Me.Nick { return } channel := conn.GetChannel(line.Args[0]) if channel == nil || !channel.Modes.Moderated { return } privs := conn.Me.Channels[channel] if !(privs.Op || privs.Admin || privs.HalfOp || privs.Owner) { return } nick := conn.GetNick(line.Nick) if nick == nil { return } if hasAccess(conn, nick, line.Nick, "v") { conn.Mode(line.Args[0], "+v "+line.Nick) } }
func tempban(conn *irc.Conn, nick *irc.Nick, args, target string) { channel, args := parseAccess(conn, nick, target, args, "oh") if channel == "" || args == "" { return } ch := conn.GetChannel(channel) if ch == nil { say(conn, target, "%s: Unable to get channel information about %s", nick.Nick, channel) return } args = strings.TrimSpace(args) split := strings.SplitN(args, " ", 3) dur, err := strconv.Atoi64(split[1]) if dur < 5 { dur = 5 split[1] = "5" } if err != nil { say(conn, channel, "Format: !tb <nick> <minutes> <reason>") return } n := conn.GetNick(split[0]) if n == nil || (split[0] != nick.Nick && (!hasAccess(conn, nick, channel, "o") && hasAccess(conn, n, channel, "oh"))) { return } conn.Mode(channel, "+b *!*@"+n.Host) reason := "(" + nick.Nick + ")" if len(split) == 3 { reason += " " + split[2] } reason += " (" + split[1] + " min.)" conn.Kick(channel, split[0], reason) expiry := time.Seconds() + dur*60 banLogAdd("*!*@"+n.Host, split[0], reason, channel, expiry) }