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
}
Example #4
0
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)
	}

}