func (m *Method) Query(conn *irc.Conn, channelName string) (*Result, error) { res, err := m.query(conn, channelName) if err != nil { return nil, err } res.Name = channelName res.Server = conn.GetServer() return res, nil }
func listQuery(conn *irc.Conn, channelName string) (*Result, error) { conn.SendRawf("LIST %s", channelName) numusers := 0 topic := "" received322 := false for { ev, err := conn.WaitUntil( "322", // RPL_LIST "323", // RPL_LISTEND "401", // ERR_NOSUCHNICK (nick/channel) "403", // ERR_NOSUCHCHANNEL ) if err != nil { return nil, err } switch ev.Code { case "322": received322 = true if len(ev.Args) < 4 { return nil, fmt.Errorf("Unexpectedly short LIST response on %s", channelName) } numusers, err = strconv.Atoi(ev.Args[2]) if err != nil { return nil, fmt.Errorf("Failed to parse number of channel users: %s", err.Error()) } topic = ev.Args[3] case "323": if received322 == false { return nil, fmt.Errorf("No status data for %s received on query", channelName) } goto ret case "401": fallthrough case "403": return nil, fmt.Errorf("No such channel, '%s'", channelName) } } ret: return &Result{ NumberOfUsers: numusers, Topic: topic, }, nil }
func joinQuery(conn *irc.Conn, channelName string) (*Result, error) { conn.SendRawf("JOIN %s", channelName) conn.SendRawf("TOPIC %s", channelName) numusers := 0 topic := "" receivedTopic, receivedNames := false, false for { ev, err := conn.WaitUntil( "353", // RPL_NAMREPLY "366", // RPL_ENDOFNAMES "331", // RPL_NOTOPIC "332", // RPL_TOPIC "422", // ERR_NOMOTD ) if err != nil { return nil, err } switch ev.Code { case "353": if len(ev.Args) != 0 { numusers += len(strings.Split(ev.Args[len(ev.Args)-1], " ")) } case "332": topic = ev.Args[len(ev.Args)-1] receivedTopic = true case "366": receivedNames = true case "422": continue case "331": receivedTopic = true } if receivedNames && receivedTopic { break } } // TODO: Make it possible to add a parting message conn.SendRawf("PART %s", channelName) return &Result{ NumberOfUsers: numusers, Topic: topic, }, nil }
func channelCheckServer(ctx *mainContext, db *sql.DB, network *dbNetwork, chs []channel) { defer func() { err, isErr := recover().(error) if isErr { log.Printf("Error occurred while checking channels on '%s': %s\n", network.network, err.Error()) } }() network_chs := []channel{} for _, ch := range chs { if ch.Network() != network.network { continue } if ch.Checked() { dur := time.Now().Sub(ch.CheckTime()) if dur < time.Hour*24*7 { continue } } network_chs = append(network_chs, ch) } if len(network_chs) == 0 { return } log.Printf("Checking channels on %s.\n", network.network) var bot *irc.Conn var err error for _, server := range network.servers { bot, err = irc.Connect(server, ctx.conf.IRCBotNickname(), ctx.conf.IRCBotRealname(), nil) if err != nil { log.Printf("Failed to connect to %s: %s.\n", server, err.Error()) continue } defer bot.Disconnect() break } if bot == nil { log.Printf("Could not connect to any address associated with %s.\n", network.network) return } for _, ch := range network_chs { if ch.Network() != network.network { continue } log.Printf("Checking %s@%s.\n", ch.Name(), ch.Network()) status, method, err := channelCheck(bot, ch.Name()) str := "" if err != nil { str = err.Error() err = dbUpdateStatus(db, ch.Name(), ch.Network(), 0, "", "fail", str, time.Now()) } else { log.Printf("%s@%s %d Topic: %s\n", ch.Name(), ch.Network(), status.NumberOfUsers, status.Topic) err = dbUpdateStatus(db, ch.Name(), ch.Network(), status.NumberOfUsers, status.Topic, method, str, time.Now()) } if err != nil { log.Fatalf("Database error when updating channel status: %s.\n", err.Error()) } time.Sleep(5 * time.Second) } }