Exemple #1
1
// Message receives a Message struct and sends it to appropriate channels
func Message(s *discordgo.Session, m *types.Message) error {
	message := strings.Join(m.Payload, "\n")
	var channels []string
	var dchannels []*discordgo.Channel
	var err error
	c := config.Get()

	if m.Prefix != "" {
		message = fmt.Sprintf("%s: %s", m.Prefix, message)
	}

	if m.Channels[0] == "*" {
		dchannels, err = s.GuildChannels(c.Guild)

		if err != nil {
			return err
		}
		//errhandler.Handle(err)

		for _, chann := range dchannels {
			channels = append(channels, chann.ID)
		}

	} else {
		channels = m.Channels
	}
	log.Debugf("%s\n", len(channels))

	for _, channel := range channels {
		s.ChannelMessageSend(channel, message)
	}
	return nil
}
Exemple #2
0
// Listen Tells Gin API to start
func Listen(iface string, s *discordgo.Session, logger *logging.Logger) {
	// set the refs to point to main
	var v1 *gin.RouterGroup
	session = s
	c := config.Get()
	log = logger

	if c.LogLevel != "debug" {
		gin.SetMode(gin.ReleaseMode)
	}

	//r := gin.Default()
	r := gin.New()

	r.Use(loggerino())
	r.Use(gin.Recovery())

	if c.APIPassword != "" {
		log.Info("Basic Authentication enabled for API")
		v1 = r.Group("/v1", gin.BasicAuth(gin.Accounts{
			c.APIUsername: c.APIPassword,
		}))
	} else {
		log.Warning("DIGO_API_PASSWORD and DIGO_API_USERNAME are not set")
		log.Warning("The API is open to all requests")
		v1 = r.Group("/v1")
	}

	v1.GET("/version", versionV1)
	v1.GET("/channels", channelsV1)
	v1.POST("/message", messageV1)

	go r.Run(iface)
	log.Noticef("Digo API is listening on %s", c.APIInterface)
}
Exemple #3
0
/* may be deprecated by session.Status in discordgo */
func pollConn(s *discordgo.Session) {
	c := config.Get()
	for {
		time.Sleep(10 * time.Second)
		found := false
		guilds, err := s.UserGuilds()
		for _, g := range guilds {
			if g.ID == c.Guild {
				found = true
				break
			}
		}

		if !found {
			log.Warningf("Could not find membership matching guild ID. %s", c.Guild)
			log.Warningf("Maybe I need a new invite? Using code %s", c.InviteID)
			if s.Token != "" {
				s.Close()
			}
			return
		}

		if err != nil {
			log.Warningf("Could not fetch guild info %v", err)
			if s.Token != "" {
				s.Close()
			}
			return
		}
	}
}
Exemple #4
0
// Register function builds the Plugins struct and calls "register" on each
// plugin
func Register() (found bool) {
	var pluginFiles []string
	var enabledPlugins []string
	var plugin *types.Plugin
	var err error
	c := config.Get()

	// build top level trigger cache
	p.AllTriggers = map[string]string{
		c.Trigger: "__internal",
	}

	p.Directory, pluginFiles, err = searchPluginDir()
	log.Debug("Potential plugins: %v\n", pluginFiles)
	if err != nil {
		found = false
		log.Warning("Problem with plugins directory: %s\n", err)
		return
	}
	found = true

	for _, pluginName := range pluginFiles {
		plugin, err = registerPlugin(p.Directory, pluginName)
		if err != nil {
			log.Warningf("Could not register %s: %s\n", pluginName, err)
		} else {
			p.Plugins[pluginName] = plugin
			enabledPlugins = append(enabledPlugins, plugin.Name)
		}
	}

	log.Noticef("Enabled Plugins: %s", strings.Join(enabledPlugins, ", "))

	return found
}
Exemple #5
0
func registerPlugin(dir string, file string) (plugin *types.Plugin, err error) {
	c := config.Get()
	// register string is hardcoded, always the first argument
	config, err := Exec(dir, file, []string{"register"})
	err = json.Unmarshal(config, &plugin)
	if err != nil {
		err = fmt.Errorf("Couldn't run \"%s register\"\n", file)
		log.Errorf("%s\n", err)
		log.Debugf("%s\n", config)
		return
	}
	// default to simple type plugin
	if plugin.Type == "" {
		plugin.Type = "simple"
	}

	if plugin.Filename == "" {
		plugin.Filename = file
	}

	// input validation
	if len(plugin.Triggers) == 0 && len(plugin.Tokens) == 0 {
		err = fmt.Errorf("Plugin \"%s\" does nothing! It has no triggers or tokens. Not registering.", file)
		return
	}

	if plugin.Type == "simple" {
		log.Debugf("Simple plugin %s registered", plugin.Name)
	} else if plugin.Type == "json" {
		log.Debug("JSON plugin %s registered", plugin.Name)
	} else {
		log.Warningf("Plugin of unknown type registered: %s", plugin.Type)
		log.Warning("Valid types: simple, json")
		err = errors.New("Unknown plugin type")
		return
	}

	// trigger cache so we only have to iterate one set per message
	for _, trigger := range plugin.Triggers {
		// sorry, can't override /bot
		if trigger == c.Trigger {
			log.Info("Prevented plugin %s from trying to override bot trigger %s.", plugin.Name, c.Trigger)
			continue
		}
		p.AllTriggers[trigger] = file
	}

	// token cache so we only have to iterate one set per message
	for _, token := range plugin.Tokens {
		p.AllTokens[token] = file
	}
	//spew.Dump(config)
	return
}
Exemple #6
0
func acceptInvite(s *discordgo.Session) error {
	var err error
	c := config.Get()
	//time.Sleep(1 * time.Second)
	if c.InviteID != "" {
		log.Debugf("Attempting to accept invite: %s", c.InviteID)
		_, err = s.InviteAccept(c.InviteID)
	} else {
		log.Debug("No DIGO_INVITE_ID specified, no invite to accept.")
	}
	return err
}
Exemple #7
0
func channelsV1(c *gin.Context) {
	// this route is expensive since it's doing live fetching of channel information
	// expensive as in ~100ms
	var ch []*discordgo.Channel
	var err error
	config := config.Get()
	ch, err = session.GuildChannels(config.Guild)
	if err != nil {
		c.JSON(500, gin.H{
			"message": "Could not fetch channel information",
			"error":   fmt.Sprintf("%s", err),
		})
	} else {
		c.JSON(200, ch)
	}
}
Exemple #8
0
func main() {
	var err error

	//p = plugins.Init()
	lock := make(chan int)

	// set up the config struct
	config.Init()

	// set the log reference to pass around
	log := logger.Init()
	errhandler.Init(log)

	// set up the plugins struct
	p := plugins.Init(log)
	//log.Notice()

	// handler takes reference to config and plugins structs
	handler.Init(p, log)

	// login / websocket flow
	s := conn.Init(log)

	// determine the bot's userID
	user, err := s.User("@me")
	errhandler.Handle(err)

	c := config.Get()

	c.UserID = user.ID

	// listen for events on Discord
	// conn.Listen(s, c, log)

	// enable the API, if applicable
	if c.DisableAPI {
		log.Notice("API explicitly disabled.")
	} else {
		go api.Listen(c.APIInterface, s, log)
	}

	log.Noticef("Digo v%s Online", globals.Version)

	<-lock
}
Exemple #9
0
func doLogin(s *discordgo.Session) error {
	var err error
	var token string
	c := config.Get()
	log.Debug("Logging in")
	token, err = s.Login(c.Email, c.Password)
	if err == nil {
		if token != "" {
			s.Token = token
		}
	} else {
		log.Errorf("Can't log in: %s", err)
		log.Error("Maybe your credentials are invalid?")
	}

	// since we're dealing with a ref, only return the error
	return err
}
Exemple #10
0
// MessageHandler is the callback for the discordgo session
func MessageHandler(s *discordgo.Session, m *discordgo.Message) {
	var status int
	var command []string
	var handled bool
	c := config.Get()

	log.Infof("%s %s > %s", m.ChannelID, m.Author.Username, m.Content)

	// prevent the bot from triggering itself
	if m.Author.ID == c.UserID {
		return
	}

	// the /bot (or whatever) trigger always has precedence
	status, command = checkTrigger(c.Trigger, m.Content)

	handled = handleInternalCommand(status, command, s, m)
	if handled {
		return
	}

	// clean up the command
	// if status != globals.NOMATCH {
	// }

	for trigger, pluginFile := range p.AllTriggers {
		// grab the correct plugin from the Plugins struct
		plugin := p.Plugins[pluginFile]

		status, command = checkTrigger(trigger, m.Content)
		handled = handleExternalCommand(status, command, p.Directory, plugin, s, m)
		if handled {
			return
		}

	}
}
Exemple #11
0
func messageDelete(s *discordgo.Session, chanID string, mID string) {
	c := config.Get()
	if !c.KeepTriggers {
		s.ChannelMessageDelete(chanID, mID)
	}
}
Exemple #12
0
// Init sets up the Logger
func Init() *logging.Logger {
	var log = logging.MustGetLogger("Digo")
	var llevel logging.Level
	var useStdout bool
	var useLogfile bool
	c := config.Get()

	// scoping made this a requirement //
	var logfileBackend *logging.LogBackend
	var logfileBackendFormatter logging.Backend
	var logfileBackendLeveled logging.LeveledBackend

	var stdoutBackend *logging.LogBackend
	var stdoutBackendFormatter logging.Backend
	var stdoutBackenedLeveled logging.LeveledBackend
	//                                 //

	// log streams. ["stdout"] || ["file"] || ["stdout", "file"]
	for _, item := range strings.Split(c.LogStreams, ",") {
		switch {
		case item == "stdout":
			useStdout = true
		case item == "file":
			useLogfile = true
		}
	}

	llevel = setLoglevel(c.LogLevel, c)

	// If you want to completely suppress program output, redirect it to /dev/null
	if !useStdout && !useLogfile {
		fmt.Println("Explicitly enabling stdout")
		useStdout = true
		useLogfile = false // probably don't explicitly need this
	}

	if useLogfile {
		logfile, success := openLogfile(c.LogFile)
		if success {
			var logfileFormat = logging.MustStringFormatter(
				`%{time:15:04:05} %{shortfunc} > %{level:.4s} %{id:03x} %{message}`,
			)
			logfileBackend = logging.NewLogBackend(logfile, "", 0)
			logfileBackendFormatter = logging.NewBackendFormatter(logfileBackend, logfileFormat)
			logfileBackendLeveled = logging.AddModuleLevel(logfileBackendFormatter)
			//logfileBackendLeveled.SetLevel(llevel, "Digo")
			logfileBackendLeveled.SetLevel(logging.DEBUG, "Digo")
			// log stuff
		} else {
			fmt.Println("Disabled logfile")
			useLogfile = false
		}
	}

	if useStdout {
		var stdoutFormat = logging.MustStringFormatter(
			`%{color}%{time:15:04:05} %{shortfunc} > %{level:.4s} %{id:03x}%{color:reset} %{message}`,
		)
		stdoutBackend = logging.NewLogBackend(os.Stdout, "", 0)
		stdoutBackendFormatter = logging.NewBackendFormatter(stdoutBackend, stdoutFormat)
		stdoutBackenedLeveled = logging.AddModuleLevel(stdoutBackendFormatter)
		stdoutBackenedLeveled.SetLevel(llevel, "Digo")
	}

	switch {
	case useStdout && useLogfile:
		logging.SetBackend(stdoutBackenedLeveled, logfileBackendLeveled)
	case useStdout:
		logging.SetBackend(stdoutBackenedLeveled)
	case useLogfile:
		logging.SetBackend(logfileBackendLeveled)
	default:
		fmt.Println("Error: Could not enable any output.")
		os.Exit(2)

	}

	log.Debug("Logger initialized")

	return log
}