コード例 #1
0
ファイル: urls.go プロジェクト: gundalow/sp0rkle
// TODO(fluffle): thisisn't quite PseudoRand but still ...
func (uc *Collection) GetRand(regex string) *Url {
	lookup := bson.M{}
	if regex != "" {
		// Perform a regex lookup if we have one
		lookup["url"] = bson.M{"$regex": regex, "$options": "i"}
	}
	query := uc.Find(lookup)
	count, err := query.Count()
	if err != nil {
		logging.Warn("Count for URL lookup '%s' failed: %s", regex, err)
		return nil
	}
	if count == 0 {
		return nil
	}
	var res Url
	if count > 1 {
		query.Skip(rand.Intn(count))
	}
	if err = query.One(&res); err != nil {
		logging.Warn("Fetch for URL lookup '%s' failed: %s", regex, err)
		return nil
	}
	return &res
}
コード例 #2
0
ファイル: tracker.go プロジェクト: Gonk/goirc
// Removes a Nick from being tracked.
func (st *stateTracker) DelNick(n string) {
	if nk, ok := st.nicks[n]; ok {
		if nk != st.me {
			st.delNick(nk)
		} else {
			logging.Warn("Tracker.DelNick(): won't delete myself.")
		}
	} else {
		logging.Warn("Tracker.DelNick(): %s not tracked.", n)
	}
}
コード例 #3
0
ファイル: quotes.go プロジェクト: gundalow/sp0rkle
// TODO(fluffle): reduce duplication with lib/factoids?
func (qc *Collection) GetPseudoRand(regex string) *Quote {
	lookup := bson.M{}
	if regex != "" {
		// Only perform a regex lookup if there's a regex to match against,
		// otherwise this just fetches a quote at pseudo-random.
		lookup["quote"] = bson.M{"$regex": regex, "$options": "i"}
	}
	ids, ok := qc.seen[regex]
	if ok && len(ids) > 0 {
		logging.Debug("Looked for quotes matching '%s' before, %d stored id's",
			regex, len(ids))
		lookup["_id"] = bson.M{"$nin": ids}
	}
	query := qc.Find(lookup)
	count, err := query.Count()
	if err != nil {
		logging.Warn("Count for quote lookup '%s' failed: %s", regex, err)
		return nil
	}
	if count == 0 {
		if ok {
			// Looked for this regex before, but nothing matches now
			delete(qc.seen, regex)
		}
		return nil
	}
	var res Quote
	if count > 1 {
		query = query.Skip(rand.Intn(count))
	}
	if err = query.One(&res); err != nil {
		logging.Warn("Fetch for quote lookup '%s' failed: %s", regex, err)
		return nil
	}
	if count != 1 {
		if !ok {
			// only store seen for regex that match more than one quote
			logging.Debug("Creating seen data for regex '%s'.", regex)
			qc.seen[regex] = make([]bson.ObjectId, 0, count)
		}
		logging.Debug("Storing id %v for regex '%s'.", res.Id, regex)
		qc.seen[regex] = append(qc.seen[regex], res.Id)
	} else if ok {
		// if the count of results is 1 and we're storing seen data for regex
		// then we've exhausted the possible results and should wipe it
		logging.Debug("Zeroing seen data for regex '%s'.", regex)
		delete(qc.seen, regex)
	}
	return &res
}
コード例 #4
0
ファイル: tracker.go プロジェクト: Gonk/goirc
// Dissociates an already known nick from an already known channel.
// Does some tidying up to stop tracking nicks we're no longer on
// any common channels with, and channels we're no longer on.
func (st *stateTracker) Dissociate(ch *Channel, nk *Nick) {
	if ch == nil || nk == nil {
		logging.Error("Tracker.Dissociate(): passed nil values :-(")
	} else if _ch, ok := st.chans[ch.Name]; !ok || ch != _ch {
		// As we can implicitly delete both nicks and channels from being
		// tracked by dissociating one from the other, we should verify that
		// we're not being passed an old Nick or Channel.
		logging.Error("Tracker.Dissociate(): channel %s not found in "+
			"(or differs from) internal state.", ch.Name)
	} else if _nk, ok := st.nicks[nk.Nick]; !ok || nk != _nk {
		logging.Error("Tracker.Dissociate(): nick %s not found in "+
			"(or differs from) internal state.", nk.Nick)
	} else if _, ok := nk.IsOn(ch); !ok {
		logging.Warn("Tracker.Dissociate(): %s not on %s.",
			nk.Nick, ch.Name)
	} else if nk == st.me {
		// I'm leaving the channel for some reason, so it won't be tracked.
		st.delChannel(ch)
	} else {
		// Remove the nick from the channel and the channel from the nick.
		ch.delNick(nk)
		nk.delChannel(ch)
		if len(nk.chans) == 0 {
			// We're no longer in any channels with this nick.
			st.delNick(nk)
		}
	}
}
コード例 #5
0
ファイル: tracker.go プロジェクト: Gonk/goirc
// Associates an already known nick with an already known channel.
func (st *stateTracker) Associate(ch *Channel, nk *Nick) *ChanPrivs {
	if ch == nil || nk == nil {
		logging.Error("Tracker.Associate(): passed nil values :-(")
		return nil
	} else if _ch, ok := st.chans[ch.Name]; !ok || ch != _ch {
		// As we can implicitly delete both nicks and channels from being
		// tracked by dissociating one from the other, we should verify that
		// we're not being passed an old Nick or Channel.
		logging.Error("Tracker.Associate(): channel %s not found in "+
			"(or differs from) internal state.", ch.Name)
		return nil
	} else if _nk, ok := st.nicks[nk.Nick]; !ok || nk != _nk {
		logging.Error("Tracker.Associate(): nick %s not found in "+
			"(or differs from) internal state.", nk.Nick)
		return nil
	} else if _, ok := nk.IsOn(ch); ok {
		logging.Warn("Tracker.Associate(): %s already on %s.",
			nk.Nick, ch.Name)
		return nil
	}
	cp := new(ChanPrivs)
	ch.addNick(nk, cp)
	nk.addChannel(ch, cp)
	return cp
}
コード例 #6
0
ファイル: tracker.go プロジェクト: Gonk/goirc
// Removes a Channel from being tracked.
func (st *stateTracker) DelChannel(c string) {
	if ch, ok := st.chans[c]; ok {
		st.delChannel(ch)
	} else {
		logging.Warn("Tracker.DelChannel(): %s not tracked.", c)
	}
}
コード例 #7
0
ファイル: factoids.go プロジェクト: fluffle/sp0rkle
func (fc *Collection) InfoMR(key string) *FactoidInfo {
	mr := &mgo.MapReduce{
		Map: `function() { emit("count", {
			accessed: this.accessed.count,
			modified: this.modified.count,
			created: this.created.count,
		})}`,
		Reduce: `function(k,l) {
			var sum = { accessed: 0, modified: 0, created: 0 };
			for each (var v in l) {
				sum.accessed += v.accessed;
				sum.modified += v.modified;
				sum.created  += v.created;
			}
			return sum;
		}`,
	}
	var res []struct {
		Id    int `bson:"_id"`
		Value FactoidInfo
	}
	info, err := fc.Find(lookup(key)).MapReduce(mr, &res)
	if err != nil || len(res) == 0 {
		logging.Warn("Info MR for '%s' failed: %v", key, err)
		return nil
	} else {
		logging.Debug("Info MR mapped %d, emitted %d, produced %d in %d ms.",
			info.InputCount, info.EmitCount, info.OutputCount, info.Time/1e6)
	}
	return &res[0].Value
}
コード例 #8
0
ファイル: state_handlers.go プロジェクト: Jyggafey/drone
// Handle JOINs to channels to maintain state
func (conn *Conn) h_JOIN(line *Line) {
	ch := conn.ST.GetChannel(line.Args[0])
	nk := conn.ST.GetNick(line.Nick)
	if ch == nil {
		// first we've seen of this channel, so should be us joining it
		// NOTE this will also take care of nk == nil && ch == nil
		if nk != conn.Me {
			logging.Warn("irc.JOIN(): JOIN to unknown channel %s received "+
				"from (non-me) nick %s", line.Args[0], line.Nick)
			return
		}
		ch = conn.ST.NewChannel(line.Args[0])
		// since we don't know much about this channel, ask server for info
		// we get the channel users automatically in 353 and the channel
		// topic in 332 on join, so we just need to get the modes
		conn.Mode(ch.Name)
		// sending a WHO for the channel is MUCH more efficient than
		// triggering a WHOIS on every nick from the 353 handler
		conn.Who(ch.Name)
	}
	if nk == nil {
		// this is the first we've seen of this nick
		nk = conn.ST.NewNick(line.Nick)
		nk.Ident = line.Ident
		nk.Host = line.Host
		// since we don't know much about this nick, ask server for info
		conn.Who(nk.Nick)
	}
	// this takes care of both nick and channel linking \o/
	conn.ST.Associate(ch, nk)
}
コード例 #9
0
ファイル: module.go プロジェクト: Gonk/Gonk
func _console_log(args ...interface{}) interface{} {
	for _, arg := range args {
		log.Warn("> %s", arg)
	}

	return ""
}
コード例 #10
0
ファイル: tracker.go プロジェクト: Gonk/goirc
// Creates a new Channel, initialises it, and stores it so it
// can be properly tracked for state management purposes.
func (st *stateTracker) NewChannel(c string) *Channel {
	if _, ok := st.chans[c]; ok {
		logging.Warn("Tracker.NewChannel(): %s already tracked.", c)
		return nil
	}
	st.chans[c] = NewChannel(c)
	return st.chans[c]
}
コード例 #11
0
ファイル: tracker.go プロジェクト: Gonk/goirc
// Creates a new Nick, initialises it, and stores it so it
// can be properly tracked for state management purposes.
func (st *stateTracker) NewNick(n string) *Nick {
	if _, ok := st.nicks[n]; ok {
		logging.Warn("Tracker.NewNick(): %s already tracked.", n)
		return nil
	}
	st.nicks[n] = NewNick(n)
	return st.nicks[n]
}
コード例 #12
0
ファイル: seen.go プロジェクト: pzsz/sp0rkle
func (sc *Collection) TopTen(ch string) []Nick {
	var res []Nick
	q := sc.Find(bson.M{"action": "LINES", "chan": ch}).Sort("-lines").Limit(10)
	if err := q.All(&res); err != nil {
		logging.Warn("TopTen Find error: %v", err)
	}
	return res
}
コード例 #13
0
ファイル: state_handlers.go プロジェクト: Jyggafey/drone
// Handle 671 whois reply (nick connected via SSL)
func (conn *Conn) h_671(line *Line) {
	if nk := conn.ST.GetNick(line.Args[1]); nk != nil {
		nk.Modes.SSL = true
	} else {
		logging.Warn("irc.671(): received WHOIS SSL info for unknown nick %s",
			line.Args[1])
	}
}
コード例 #14
0
ファイル: state_handlers.go プロジェクト: Jyggafey/drone
// Handle TOPIC changes for channels
func (conn *Conn) h_TOPIC(line *Line) {
	if ch := conn.ST.GetChannel(line.Args[0]); ch != nil {
		ch.Topic = line.Args[1]
	} else {
		logging.Warn("irc.TOPIC(): topic change on unknown channel %s",
			line.Args[0])
	}
}
コード例 #15
0
ファイル: state_handlers.go プロジェクト: Jyggafey/drone
// Handle 332 topic reply on join to channel
func (conn *Conn) h_332(line *Line) {
	if ch := conn.ST.GetChannel(line.Args[1]); ch != nil {
		ch.Topic = line.Args[2]
	} else {
		logging.Warn("irc.332(): received TOPIC value for unknown channel %s",
			line.Args[1])
	}
}
コード例 #16
0
ファイル: nick.go プロジェクト: Jyggafey/drone
// Disassociates a Channel from a Nick.
func (nk *Nick) delChannel(ch *Channel) {
	if _, ok := nk.chans[ch]; ok {
		delete(nk.chans, ch)
		delete(nk.lookup, ch.Name)
	} else {
		logging.Warn("Nick.delChannel(): %s not on %s.", nk.Nick, ch.Name)
	}
}
コード例 #17
0
ファイル: state_handlers.go プロジェクト: Jyggafey/drone
// Handle MODE changes for channels we know about (and our nick personally)
func (conn *Conn) h_MODE(line *Line) {
	if ch := conn.ST.GetChannel(line.Args[0]); ch != nil {
		// channel modes first
		ch.ParseModes(line.Args[1], line.Args[2:]...)
	} else if nk := conn.ST.GetNick(line.Args[0]); nk != nil {
		// nick mode change, should be us
		if nk != conn.Me {
			logging.Warn("irc.MODE(): recieved MODE %s for (non-me) nick %s",
				line.Args[1], line.Args[0])
			return
		}
		nk.ParseModes(line.Args[1])
	} else {
		logging.Warn("irc.MODE(): not sure what to do with MODE %s",
			strings.Join(line.Args, " "))
	}
}
コード例 #18
0
ファイル: nick.go プロジェクト: Jyggafey/drone
// Associates a Channel with a Nick.
func (nk *Nick) addChannel(ch *Channel, cp *ChanPrivs) {
	if _, ok := nk.chans[ch]; !ok {
		nk.chans[ch] = cp
		nk.lookup[ch.Name] = ch
	} else {
		logging.Warn("Nick.addChannel(): %s already on %s.", nk.Nick, ch.Name)
	}
}
コード例 #19
0
ファイル: channel.go プロジェクト: Jyggafey/drone
// Disassociates a Nick from a Channel.
func (ch *Channel) delNick(nk *Nick) {
	if _, ok := ch.nicks[nk]; ok {
		delete(ch.nicks, nk)
		delete(ch.lookup, nk.Nick)
	} else {
		logging.Warn("Channel.delNick(): %s not on %s.", nk.Nick, ch.Name)
	}
}
コード例 #20
0
ファイル: channel.go プロジェクト: Jyggafey/drone
// Associates a Nick with a Channel
func (ch *Channel) addNick(nk *Nick, cp *ChanPrivs) {
	if _, ok := ch.nicks[nk]; !ok {
		ch.nicks[nk] = cp
		ch.lookup[nk.Nick] = nk
	} else {
		logging.Warn("Channel.addNick(): %s already on %s.", nk.Nick, ch.Name)
	}
}
コード例 #21
0
ファイル: state_handlers.go プロジェクト: Jyggafey/drone
// Handle 324 mode reply
func (conn *Conn) h_324(line *Line) {
	if ch := conn.ST.GetChannel(line.Args[1]); ch != nil {
		ch.ParseModes(line.Args[2], line.Args[3:]...)
	} else {
		logging.Warn("irc.324(): received MODE settings for unknown channel %s",
			line.Args[1])
	}
}
コード例 #22
0
ファイル: handlers.go プロジェクト: gundalow/sp0rkle
func recordNick(ctx *bot.Context) {
	sn := seenNickFromLine(ctx)
	sn.Chan = ""
	sn.Text = ctx.Target()
	if _, err := sc.Upsert(sn.Id(), sn); err != nil {
		// We don't have anyone to reply to in this case, so log instead.
		logging.Warn("Failed to store seen data: %v", err)
	}
}
コード例 #23
0
ファイル: handlers.go プロジェクト: pzsz/sp0rkle
func recordNick(line *base.Line) {
	sn := seenNickFromLine(line)
	sn.Chan = ""
	sn.Text = line.Args[0]
	if _, err := sc.Upsert(sn.Id(), sn); err != nil {
		// We don't have anyone to reply to in this case, so log instead.
		logging.Warn("Failed to store seen data: %v", err)
	}
}
コード例 #24
0
ファイル: factoids.go プロジェクト: fluffle/sp0rkle
func (fc *Collection) GetKeysMatching(regex string) []string {
	var res []string
	query := fc.Find(bson.M{"key": bson.M{"$regex": regex}})
	if err := query.Distinct("key", &res); err != nil {
		logging.Warn("Distinct regex query for '%s' failed: %v\n", regex, err)
		return nil
	}
	return res
}
コード例 #25
0
ファイル: state_handlers.go プロジェクト: Jyggafey/drone
// Handle 311 whois reply
func (conn *Conn) h_311(line *Line) {
	if nk := conn.ST.GetNick(line.Args[1]); nk != nil && nk != conn.Me {
		nk.Ident = line.Args[2]
		nk.Host = line.Args[3]
		nk.Name = line.Args[5]
	} else {
		logging.Warn("irc.311(): received WHOIS info for unknown nick %s",
			line.Args[1])
	}
}
コード例 #26
0
ファイル: tracker.go プロジェクト: Gonk/goirc
// Signals to the tracker that a Nick should be tracked
// under a "neu" nick rather than the old one.
func (st *stateTracker) ReNick(old, neu string) {
	if nk, ok := st.nicks[old]; ok {
		if _, ok := st.nicks[neu]; !ok {
			nk.Nick = neu
			delete(st.nicks, old)
			st.nicks[neu] = nk
			for ch, _ := range nk.chans {
				// We also need to update the lookup maps of all the channels
				// the nick is on, to keep things in sync.
				delete(ch.lookup, old)
				ch.lookup[neu] = nk
			}
		} else {
			logging.Warn("Tracker.ReNick(): %s already exists.", neu)
		}
	} else {
		logging.Warn("Tracker.ReNick(): %s not tracked.", old)
	}
}
コード例 #27
0
ファイル: seen.go プロジェクト: gundalow/sp0rkle
func (sc *Collection) SeenAnyMatching(rx string) []string {
	var res []string
	q := sc.Find(bson.M{"key": bson.M{"$regex": rx, "$options": "i"}}).Sort("-timestamp")
	if err := q.Distinct("key", &res); err != nil {
		logging.Warn("SeenAnyMatching Find error: %v", err)
		return []string{}
	}
	logging.Debug("Looked for matches, found %#v", res)
	return res
}
コード例 #28
0
ファイル: handlers.go プロジェクト: pzsz/sp0rkle
func load(line *base.Line) {
	// We're connected to IRC, so load saved reminders
	r := rc.LoadAndPrune()
	for i := range r {
		if r[i] == nil {
			logging.Warn("Nil reminder %d from LoadAndPrune", i)
			continue
		}
		Remind(r[i])
	}
}
コード例 #29
0
ファイル: handlers.go プロジェクト: gundalow/sp0rkle
func load(ctx *bot.Context) {
	// We're connected to IRC, so load saved reminders
	r := rc.LoadAndPrune()
	for i := range r {
		if r[i] == nil {
			logging.Warn("Nil reminder %d from LoadAndPrune", i)
			continue
		}
		Remind(r[i], ctx)
	}
}
コード例 #30
0
ファイル: bot.go プロジェクト: gundalow/sp0rkle
func Shutdown() {
	lock.Lock()
	defer lock.Unlock()
	if bot == nil {
		logging.Fatal("Called Shutdown() before Init().")
	}
	if !bot.connected {
		logging.Warn("Not connected to servers.")
	}
	bot.connected = false
	bot.servers.Shutdown(false)
}