Example #1
0
File: bot.go Project: pzsz/sp0rkle
func Connect() bool {
	lock.Lock()
	defer lock.Unlock()
	if irc == nil {
		logging.Fatal("Called Connect() before Init().")
	}
	return connectLoop()
}
Example #2
0
func (m *mongoDatabase) C(name string) Collection {
	m.Lock()
	defer m.Unlock()
	if m.sessions == nil {
		logging.Fatal("Tried to create MongoDB collection %q when disconnected.", name)
	}
	s := m.sessions[0].Copy()
	m.sessions = append(m.sessions, s)
	return &mongoCollection{Collection: s.DB(DATABASE).C(name)}
}
Example #3
0
func (b *boltDatabase) C(name string) Collection {
	b.Lock()
	defer b.Unlock()

	if b.db == nil {
		logging.Fatal("Tried to create BoltDB bucket %q when disconnected.", name)
	}

	err := b.db.Update(func(tx *bolt.Tx) error {
		if _, err := tx.CreateBucketIfNotExists([]byte(name)); err != nil {
			return err
		}
		return nil
	})
	if err != nil {
		logging.Fatal("Creating BoltDB bucket failed: %v")
	}
	return &boltBucket{name: []byte(name), db: b.db}
}
Example #4
0
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)
}
Example #5
0
func Connect() chan bool {
	lock.Lock()
	defer lock.Unlock()
	if bot == nil {
		logging.Fatal("Called Connect() before Init().")
	}
	if bot.connected {
		logging.Warn("Already connected to servers.")
	}
	bot.connected = true
	return bot.servers.Connect()
}
Example #6
0
// Wraps connecting to mongo and selecting the "sp0rkle" database.
func Init() *mgo.Database {
	lock.Lock()
	defer lock.Unlock()
	if db != nil {
		return db
	}
	s, err := mgo.Dial(*database)
	if err != nil {
		logging.Fatal("Unable to connect to MongoDB: %s", err)
	}
	session, db = s, s.DB(DATABASE)
	// Let's be explicit about requiring journaling, ehh?
	session.EnsureSafe(&mgo.Safe{J: true})
	return db
}
Example #7
0
func Client(cfg *Config) *Conn {
	logging.InitFromFlags()
	if cfg == nil || cfg.Me == nil || cfg.Me.Nick == "" || cfg.Me.Ident == "" {
		logging.Fatal("irc.Client(): Both cfg.Nick and cfg.Ident must be non-empty.")
	}
	conn := &Conn{
		cfg:        cfg,
		in:         make(chan *Line, 32),
		out:        make(chan string, 32),
		handlers:   handlerSet(),
		stRemovers: make([]Remover, 0, len(stHandlers)),
		lastsent:   time.Now(),
	}
	conn.addIntHandlers()
	conn.initialise()
	return conn
}
Example #8
0
func (b *boltDatabase) backupLoop() {
	if err := os.MkdirAll(b.dir, 0700); err != nil {
		logging.Fatal("Could not create backup dir %q: %v", b.dir, err)
	}
	// Do a backup on startup, too.
	b.doBackup()
	tick := time.NewTicker(b.every)
	for {
		select {
		case <-tick.C:
			b.doBackup()
		case <-b.quit:
			tick.Stop()
			return
		}
	}
}
Example #9
0
// Wraps connecting to mongo and selecting the "sp0rkle" database.
func Init() *mgo.Database {
	lock.Lock()
	defer lock.Unlock()
	if sessions != nil {
		// Give each caller a distinct session to avoid contention.
		s := sessions[0].Copy()
		sessions = append(sessions, s)
		return s.DB(DATABASE)
	}
	sessions = make([]*mgo.Session, 1)
	s, err := mgo.Dial(*database)
	if err != nil {
		logging.Fatal("Unable to connect to MongoDB: %s", err)
	}
	// Let's be explicit about requiring journaling, ehh?
	s.EnsureSafe(&mgo.Safe{J: true})
	sessions[0] = s
	return s.DB(DATABASE)
}
Example #10
0
File: main.go Project: pzsz/sp0rkle
func main() {
	flag.Parse()
	logging.InitFromFlags()

	// Initialise bot state
	bot.Init()

	// Connect to mongo
	db.Init()
	defer db.Close()

	// Add drivers
	calcdriver.Init()
	decisiondriver.Init()
	factdriver.Init()
	karmadriver.Init()
	markovdriver.Init()
	quotedriver.Init()
	reminddriver.Init()
	seendriver.Init()
	urldriver.Init()

	// Start up the HTTP server
	go http.ListenAndServe(*httpPort, nil)

	// Connect the bot to IRC and wait; reconnects are handled automatically.
	// If we get true back from the bot, re-exec the (rebuilt) binary.
	if bot.Connect() {
		// Calling syscall.Exec probably means deferred functions won't get
		// called, so disconnect from mongodb first for politeness' sake.
		db.Close()
		// If sp0rkle was run from PATH, we need to do that lookup manually.
		fq, _ := exec.LookPath(os.Args[0])
		logging.Warn("Re-executing sp0rkle with args '%v'.", os.Args)
		err := syscall.Exec(fq, os.Args, os.Environ())
		if err != nil {
			// hmmmmmm
			logging.Fatal("Couldn't re-exec sp0rkle: %v", err)
		}
	}
	logging.Info("Shutting down cleanly.")
}
Example #11
0
func Init() {
	uc = urls.Init()

	if err := os.MkdirAll(*urlCacheDir, 0700); err != nil {
		logging.Fatal("Couldn't create URL cache dir: %v", err)
	}

	bot.Handle(urlScan, client.PRIVMSG)

	bot.Command(find, "urlfind", "urlfind <regex>  -- "+
		"searches for previously mentioned URLs matching <regex>")
	bot.Command(find, "url find", "url find <regex>  -- "+
		"searches for previously mentioned URLs matching <regex>")
	bot.Command(find, "urlsearch", "urlsearch <regex>  -- "+
		"searches for previously mentioned URLs matching <regex>")
	bot.Command(find, "url search", "url search <regex>  -- "+
		"searches for previously mentioned URLs matching <regex>")

	bot.Command(find, "randurl", "randurl  -- displays a random URL")
	bot.Command(find, "random url", "random url  -- displays a random URL")

	bot.Command(shorten, "shorten that", "shorten that  -- "+
		"shortens the last mentioned URL.")
	bot.Command(shorten, "shorten", "shorten <url>  -- shortens <url>")

	bot.Command(cache, "cache that", "cache that  -- "+
		"caches the last mentioned URL.")
	bot.Command(cache, "cache", "cache <url>  -- caches <url>")
	bot.Command(cache, "save that", "save that  -- "+
		"caches the last mentioned URL.")
	bot.Command(cache, "save", "save <url>  -- caches <url>")

	// This serves "shortened" urls
	http.Handle(shortenPath, http.StripPrefix(shortenPath,
		http.HandlerFunc(shortenedServer)))

	// This serves "cached" urls
	http.Handle(cachePath, http.StripPrefix(cachePath,
		http.FileServer(http.Dir(*urlCacheDir))))
}
Example #12
0
File: gonk.go Project: Gonk/Gonk
func loadModules(conn *irc.Conn) (modules []IModule) {
	// Load each module in the modules directory
	scripts, err := ioutil.ReadDir("modules")
	if err != nil {
		log.Fatal(err.Error())
	}

	// Read base module script
	file, err := os.Open("module.js")
	if err != nil {
		log.Fatal("Error reading base module script:", err)
	}

	defer file.Close()

	baseScript, err := ioutil.ReadAll(file)
	if err != nil {
		log.Fatal("Error reading base module script:", err)
	}

	for _, fileInfo := range scripts {
		if !fileInfo.IsDir() {
			if !strings.HasSuffix(fileInfo.Name(), "js") {
				continue
			}

			filename := "modules/" + fileInfo.Name()

			file, err := os.Open(filename)
			if err != nil {
				log.Error("Error loading module:", err)
				continue
			}

			defer file.Close()

			script, err := ioutil.ReadAll(file)
			if err != nil {
				log.Error("Error loading module:", err)
				continue
			}

			module := NewModule(fileInfo.Name(), conn)

			// Init module with base script and its own script
			ret, err := module.Init(v8.NewContext(), string(baseScript)+string(script))

			if err != nil {
				log.Error("Error loading module: %s\n%s", err, ret)
				continue
			}

			// Create file watcher
			watcher, err := fsnotify.NewWatcher()
			if err != nil {
				log.Error("Error creating file watcher for %s:", fileInfo.Name(), err)
			}

			watcher.Watch(filename)

			go func(filename string) {
				for {
					select {
					case ev := <-watcher.Event:
						watcher.Watch(filename) // Make sure we continue to watch the file at this location

						if !ev.IsModify() {
							// Only reload the module on a modification event
							continue
						}
					case err := <-watcher.Error:
						log.Error("Error watching file: %s", filename, err)
						continue
					}

					// Reload script
					log.Info("Reloading %s", filename)

					file, err := os.Open(filename)
					if err != nil {
						log.Error("Error loading module:", err)
						continue
					}

					defer file.Close()

					script, err := ioutil.ReadAll(file)
					if err != nil {
						log.Error("Error loading module:", err)
						continue
					}

					ret, err := module.Init(v8.NewContext(), string(baseScript)+string(script))
					if err != nil {
						log.Error("Error reloading module: %s\n%s", err, ret)
					}
				}
			}(filename)

			log.Info("Loaded module %s", fileInfo.Name())
			modules = append(modules, &module)
		}
	}

	return
}
Example #13
0
func main() {
	flag.Parse()
	logging.InitFromFlags()
	golog.Init()

	// Slightly more random than 1.
	rand.Seed(time.Now().UnixNano() * int64(os.Getpid()))

	// Initialise bot state
	bot.Init()

	// Connect to mongo
	db.Init()
	defer db.Close()

	// Add drivers
	calcdriver.Init()
	decisiondriver.Init()
	factdriver.Init()
	karmadriver.Init()
	markovdriver.Init()
	netdriver.Init()
	quotedriver.Init()
	reminddriver.Init()
	seendriver.Init()
	statsdriver.Init()
	urldriver.Init()

	// Start up the HTTP server
	go http.ListenAndServe(*httpPort, nil)

	// Set up a signal handler to shut things down gracefully.
	// NOTE: net/http doesn't provide for graceful shutdown :-/
	go func() {
		called := new(int32)
		sigint := make(chan os.Signal, 1)
		signal.Notify(sigint, syscall.SIGINT)
		for _ = range sigint {
			if atomic.AddInt32(called, 1) > 1 {
				logging.Fatal("Recieved multiple interrupts, dying.")
			}
			bot.Shutdown()
		}
	}()

	// Connect the bot to IRC and wait; reconnects are handled automatically.
	// If we get true back from the bot, re-exec the (rebuilt) binary.
	if <-bot.Connect() {
		// Calling syscall.Exec probably means deferred functions won't get
		// called, so disconnect from mongodb first for politeness' sake.
		db.Close()
		// If sp0rkle was run from PATH, we need to do that lookup manually.
		fq, _ := exec.LookPath(os.Args[0])
		logging.Warn("Re-executing sp0rkle with args '%v'.", os.Args)
		err := syscall.Exec(fq, os.Args, os.Environ())
		if err != nil {
			// hmmmmmm
			logging.Fatal("Couldn't re-exec sp0rkle: %v", err)
		}
	}
	logging.Info("Shutting down cleanly.")
}