Example #1
0
// Recursively resolve pointers to other factoids
func recurse(fact *factoids.Factoid, keys map[string]bool) {
	val := fact.Value
	key, start, end := util.FactPointer(val)
	if key == "" {
		return
	}
	if _, ok := keys[key]; ok || len(keys) > 20 {
		fact.Value = val[:start] + "[circular reference]" + val[end:]
		return
	}
	keys[key] = true
	if f2 := fc.GetPseudoRand(key); f2 != nil {
		fact.Value = val[:start] + f2.Value + val[end:]
		if start == 0 && fact.Type != f2.Type {
			// Propagate change of factoid type when the pointer
			// is at the beginning of the string.
			fact.Type = f2.Type
		}
		recurse(fact, keys)
		return
	}
	// if we get here, we found a pointer key but no matching factoid
	// so recurse on the stuff after that key *only* to avoid loops.
	fact.Value = val[end:]
	recurse(fact, keys)
	fact.Value = val[:end] + fact.Value
}
Example #2
0
// Parse a single factoid value, stripping <me>/<reply>
func parseValue(k, r, v string) (ft factoids.FactoidType, fv string) {
	v = strings.TrimSpace(v)
	ft, fv = factoids.ParseValue(v)
	if ft == factoids.F_FACT && fv == v {
		// If fv == v, ParseValue hasn't stripped off a <reply>, so this is
		// just a normal factoid whose value is actually "key relation value"
		// as that's how they're stored in the old SQLite database...
		key, _, _ := util.FactPointer(fv)
		if _, ok := ptrkeys[k]; !(ok || fv == "*"+key) {
			// ... (HACK1) except if they have been used as a pointer key...
			// ... (HACK2) or if it's *just* a pointer to another factoid.
			fv = strings.Join([]string{k, r, v}, " ")
		}
	}
	return
}
Example #3
0
// Recursively resolve pointers to other factoids
func recurse(val string, keys map[string]bool) string {
	key, start, end := util.FactPointer(val)
	if key == "" {
		return val
	}
	if _, ok := keys[key]; ok || len(keys) > 20 {
		val = val[:start] + "[circular reference]" + val[end:]
		return val
	}
	keys[key] = true
	if fact := fc.GetPseudoRand(key); fact != nil {
		val = val[:start] + fact.Value + val[end:]
		return recurse(val, keys)
	}
	// if we get here, we found a pointer key but no matching factoid
	// so recurse on the stuff after that key *only* to avoid loops.
	return val[:end] + recurse(val[end:], keys)
}
Example #4
0
func main() {
	flag.Parse()
	logging.InitFromFlags()

	// Let's go find some mongo.
	db.Init()
	defer db.Close()
	fc := factoids.Init()

	// A communication channel of Factoids.
	facts := make(chan *factoids.Factoid)
	ptrs := make(chan []interface{})
	rows := make(chan []interface{})

	// Function to execute some queries on the SQLite db and shove the results
	// into the ptrs and rows channels created above.
	db_query := func(dbh *sqlite3.Database) {
		_, err := dbh.Execute("SELECT * FROM Factoids WHERE Value LIKE '%*%';", feeder(ptrs))
		close(ptrs)
		if err != nil {
			logging.Error("DB error: %s", err)
		}
		n, err := dbh.Execute("SELECT * FROM Factoids;", feeder(rows))
		close(rows)
		if err == nil {
			logging.Info("Read %d rows from database.", n)
		} else {
			logging.Error("DB error: %s", err)
		}
	}

	go func() {
		sqlite3.Session(*file, db_query)
	}()

	// First, synchronously read all the stuff from the ptrs channel
	// and build a set of all the factoid keys that are used as pointers
	for row := range ptrs {
		for _, val := range parseMultipleValues(toString(row[cValue])) {
			if key, _, _ := util.FactPointer(val); key != "" {
				ptrkeys[key] = true
			}
		}
	}

	// Now run another goroutine to munge the rows into factoids.
	// This was originally done inside the SQLite callbacks, but
	// cgo or sqlite3 obscures runtime panics and makes fail happen.
	go func() {
		for row := range rows {
			parseFactoid(row, facts)
		}
		close(facts)
	}()

	// And finally...
	count := 0
	var err error
	for fact := range facts {
		// ... push each fact into mongo
		err = fc.Insert(fact)
		if err != nil {
			logging.Error("Awww: %v\n", err)
		} else {
			if count%1000 == 0 {
				fmt.Printf("%d...", count)
			}
			count++
		}
	}
	fmt.Println("done.")
	logging.Info("Inserted %d factoids.\n", count)
}