From 28de44056c1bc9814eccf2383a621b9d9e57971c Mon Sep 17 00:00:00 2001 From: jriddick Date: Sat, 17 Jun 2017 12:35:18 +0200 Subject: [PATCH 1/2] Remove Lua Remove all references to Lua --- bot/bot_binding.go | 176 ---------------------------------- bot/config_binding.go | 91 ------------------ bot/msg_binding.go | 144 ---------------------------- config.lua | 4 - const.lua | 7 -- geoffrey.go | 95 ------------------ geoffrey.lua | 32 ------- glide.lock | 41 +------- helper/binding.go | 45 --------- {bot => helper/bot}/bot.go | 59 ++---------- {bot => helper/bot}/config.go | 0 modules/geoffrey/geoffrey.go | 155 ------------------------------ modules/plugin/plugin.go | 103 -------------------- plugins/echo.lua | 17 ---- plugins/join.lua | 15 --- plugins/ping.lua | 13 --- plugins/registration.lua | 16 ---- 17 files changed, 10 insertions(+), 1003 deletions(-) delete mode 100644 bot/bot_binding.go delete mode 100644 bot/config_binding.go delete mode 100644 bot/msg_binding.go delete mode 100644 config.lua delete mode 100644 const.lua delete mode 100644 geoffrey.lua delete mode 100644 helper/binding.go rename {bot => helper/bot}/bot.go (63%) rename {bot => helper/bot}/config.go (100%) delete mode 100644 modules/geoffrey/geoffrey.go delete mode 100644 modules/plugin/plugin.go delete mode 100644 plugins/echo.lua delete mode 100644 plugins/join.lua delete mode 100644 plugins/ping.lua delete mode 100644 plugins/registration.lua diff --git a/bot/bot_binding.go b/bot/bot_binding.go deleted file mode 100644 index 9894469..0000000 --- a/bot/bot_binding.go +++ /dev/null @@ -1,176 +0,0 @@ -package bot - -import ( - "reflect" - - log "github.com/Sirupsen/logrus" - "github.com/jriddick/geoffrey/helper" - "github.com/yuin/gopher-lua" -) - -// RegisterBot will register the Bot struct to Lua -func RegisterBot(state *lua.LState) { - // Create the Metatable - meta := state.NewTypeMetatable("bot") - state.SetGlobal("bot", meta) - - // Bind our functions - state.SetField(meta, "__index", state.NewFunction(botIndex)) -} - -// PushBot will push an existing *Bot onto the Lua stack -func PushBot(bot *Bot, state *lua.LState) { - // Create the bot user data - data := state.NewUserData() - data.Value = bot - - // Set the Metatable - state.SetMetatable(data, state.GetTypeMetatable("bot")) - - // Push the bot - state.Push(data) -} - -func checkBot(state *lua.LState) *Bot { - // Get the logger - logger := log.WithField("file", state.Where(1)) - - // Try to get the userdata - data := helper.GetUserData(1, state) - if data != nil { - // Check if userdata is the right type - if bot, ok := data.Value.(*Bot); ok { - return bot - } - - logger.Errorf("Expected userdata type Bot, we got '%s'", reflect.TypeOf(data.Value).Name()) - } - return nil -} - -func botSend(state *lua.LState) int { - if !helper.HasArguments(3, state) { - return 0 - } - - bot := checkBot(state) - rcv := helper.GetString(2, state) - msg := helper.GetString(3, state) - - if msg != nil && rcv != nil { - bot.Send(*rcv, *msg) - } - - return 0 -} - -func botJoin(state *lua.LState) int { - if !helper.HasArguments(2, state) { - return 0 - } - - bot := checkBot(state) - channel := helper.GetString(2, state) - - if channel != nil { - bot.Join(*channel) - } - - return 0 -} - -func botPing(state *lua.LState) int { - if !helper.HasArguments(2, state) { - return 0 - } - - bot := checkBot(state) - msg := helper.GetString(2, state) - - if msg != nil { - bot.Ping(*msg) - } - - return 0 -} - -func botPong(state *lua.LState) int { - if !helper.HasArguments(2, state) { - return 0 - } - - bot := checkBot(state) - msg := helper.GetString(2, state) - - if msg != nil { - bot.Pong(*msg) - } - - return 0 -} - -func botNick(state *lua.LState) int { - if !helper.HasArguments(2, state) { - return 0 - } - - bot := checkBot(state) - nick := helper.GetString(2, state) - - if nick != nil { - bot.Nick(*nick) - } - - return 0 -} - -func botUser(state *lua.LState) int { - if !helper.HasArguments(3, state) { - return 0 - } - - bot := checkBot(state) - user := helper.GetString(2, state) - name := helper.GetString(3, state) - - if user != nil && name != nil { - bot.User(*user, *name) - } - - return 0 -} - -func botIndex(state *lua.LState) int { - bot := checkBot(state) - - if bot == nil { - return 0 - } - - key := helper.GetString(2, state) - - if key == nil { - return 0 - } - - switch *key { - case "send": - state.Push(state.NewFunction(botSend)) - case "join": - state.Push(state.NewFunction(botJoin)) - case "ping": - state.Push(state.NewFunction(botPing)) - case "pong": - state.Push(state.NewFunction(botPong)) - case "nick": - state.Push(state.NewFunction(botNick)) - case "user": - state.Push(state.NewFunction(botUser)) - case "config": - PushConfig(&bot.config, state) - default: - state.Push(lua.LNil) - } - - return 1 -} diff --git a/bot/config_binding.go b/bot/config_binding.go deleted file mode 100644 index 8e7a78d..0000000 --- a/bot/config_binding.go +++ /dev/null @@ -1,91 +0,0 @@ -package bot - -import ( - "reflect" - - log "github.com/Sirupsen/logrus" - "github.com/jriddick/geoffrey/helper" - "github.com/yuin/gopher-lua" -) - -// RegisterConfig will register the Config struct to Lua -func RegisterConfig(state *lua.LState) { - // Create the Metatable - meta := state.NewTypeMetatable("config") - state.SetGlobal("config", meta) - - // Bind our functions - state.SetField(meta, "__index", state.NewFunction(configIndex)) -} - -// PushConfig will push the given config to the Lua stack -func PushConfig(config *Config, state *lua.LState) { - // Create the config user data - data := state.NewUserData() - data.Value = config - - // Set the Metatable - state.SetMetatable(data, state.GetTypeMetatable("config")) - - // Push the config - state.Push(data) -} - -func checkConfig(state *lua.LState) *Config { - // Get the logger - logger := log.WithField("file", state.Where(1)) - - // Try to get the userdata - data := helper.GetUserData(1, state) - if data != nil { - if v, ok := data.Value.(*Config); ok { - return v - } - - logger.Errorf("Expected userdata type Config but we got '%s'", reflect.TypeOf(data.Value).Name()) - } - - return nil -} - -func configIndex(state *lua.LState) int { - config := checkConfig(state) - key := helper.GetString(2, state) - - if config == nil || key == nil { - return 0 - } - - switch *key { - case "Hostname": - state.Push(lua.LString(config.Hostname)) - case "Port": - state.Push(lua.LNumber(config.Port)) - case "Secure": - state.Push(lua.LBool(config.Secure)) - case "InsecureSkipVerify": - state.Push(lua.LBool(config.InsecureSkipVerify)) - case "Nick": - state.Push(lua.LString(config.Nick)) - case "User": - state.Push(lua.LString(config.User)) - case "Name": - state.Push(lua.LString(config.Name)) - case "Channels": - channels := state.NewTable() - for key, value := range config.Channels { - channels.RawSetInt(key+1, lua.LString(value)) - } - state.Push(channels) - case "Timeout": - state.Push(lua.LNumber(config.Timeout)) - case "TimeoutLimit": - state.Push(lua.LNumber(config.TimeoutLimit)) - case "ReconnectLimit": - state.Push(lua.LNumber(config.ReconnectLimit)) - default: - state.Push(lua.LNil) - } - - return 1 -} diff --git a/bot/msg_binding.go b/bot/msg_binding.go deleted file mode 100644 index 12dff79..0000000 --- a/bot/msg_binding.go +++ /dev/null @@ -1,144 +0,0 @@ -package bot - -import ( - "reflect" - - log "github.com/Sirupsen/logrus" - "github.com/jriddick/geoffrey/helper" - "github.com/jriddick/geoffrey/msg" - "github.com/yuin/gopher-lua" -) - -// RegisterMessage will register msg.Message struct to Lua -func RegisterMessage(state *lua.LState) { - // Create the metatable - meta := state.NewTypeMetatable("message") - state.SetGlobal("message", meta) - - // Bind the message index function - state.SetField(meta, "__index", state.NewFunction(messageIndex)) - - // Create the metatable for prefix struct - prefix := state.NewTypeMetatable("prefix") - state.SetGlobal("prefix", prefix) - - // Bind the prefix index function - state.SetField(prefix, "__index", state.NewFunction(prefixIndex)) -} - -// PushMessage will push the given msg.Message to the Lua stack -func PushMessage(msg *msg.Message, state *lua.LState) { - // Create the userdata - data := state.NewUserData() - data.Value = msg - - // Set the metatable - state.SetMetatable(data, state.GetTypeMetatable("message")) - - // Push the message - state.Push(data) -} - -func pushPrefix(prefix *msg.Prefix, state *lua.LState) { - // Create the userdata - data := state.NewUserData() - data.Value = prefix - - // Set the metatable - state.SetMetatable(data, state.GetTypeMetatable("prefix")) - - // Push the prefix - state.Push(data) -} - -func checkMessage(state *lua.LState) *msg.Message { - // Get the logger - logger := log.WithField("file", state.Where(1)) - - // Try to get userdata - data := helper.GetUserData(1, state) - if data != nil { - // Check if userdata is the right type - if msg, ok := data.Value.(*msg.Message); ok { - return msg - } - - logger.Errorf("Expected userdata type msg.Message but we got '%s'", reflect.TypeOf(data.Value).Name()) - } - - return nil -} - -func checkPrefix(state *lua.LState) *msg.Prefix { - // Get the logger - logger := log.WithField("file", state.Where(1)) - - // Try to get userdata - data := helper.GetUserData(1, state) - if data != nil { - // Check if userdata is the right type - if prefix, ok := data.Value.(*msg.Prefix); ok { - return prefix - } - - logger.Errorf("Expected userdata type msg.Prefix but we got '%s'", reflect.TypeOf(data.Value).Name()) - } - - return nil -} - -func messageIndex(state *lua.LState) int { - msg := checkMessage(state) - key := helper.GetString(2, state) - - if key == nil || msg == nil { - return 0 - } - - switch *key { - case "Command": - state.Push(lua.LString(msg.Command)) - case "Params": - params := state.NewTable() - for key, param := range msg.Params { - params.RawSetInt(key+1, lua.LString(param)) - } - state.Push(params) - case "Trailing": - state.Push(lua.LString(msg.Trailing)) - case "Prefix": - pushPrefix(msg.Prefix, state) - case "Tags": - tags := state.NewTable() - for key, value := range msg.Tags { - tags.RawSetString(key, lua.LString(value)) - } - state.Push(tags) - default: - state.Push(lua.LNil) - } - - return 1 -} - -func prefixIndex(state *lua.LState) int { - prefix := checkPrefix(state) - key := helper.GetString(2, state) - - if prefix == nil || key == nil { - return 0 - } - - switch *key { - case "Name": - state.Push(lua.LString(prefix.Name)) - case "User": - state.Push(lua.LString(prefix.User)) - case "Host": - state.Push(lua.LString(prefix.Host)) - default: - state.Push(lua.LNil) - } - - return 1 -} diff --git a/config.lua b/config.lua deleted file mode 100644 index 32ea70c..0000000 --- a/config.lua +++ /dev/null @@ -1,4 +0,0 @@ -config = { - PluginFolder = "plugins", - LogLevel = INFO -} \ No newline at end of file diff --git a/const.lua b/const.lua deleted file mode 100644 index cb07df7..0000000 --- a/const.lua +++ /dev/null @@ -1,7 +0,0 @@ --- LOG LEVELS -DEBUG = 5 -INFO = 4 -WARN = 3 -ERROR = 2 -FATAL = 1 -PANIC = 0 \ No newline at end of file diff --git a/geoffrey.go b/geoffrey.go index 909867a..362b087 100644 --- a/geoffrey.go +++ b/geoffrey.go @@ -1,27 +1,9 @@ package main import ( - "fmt" "os" - "os/signal" - "syscall" - - "io/ioutil" - - "sync" - log "github.com/Sirupsen/logrus" - "github.com/jriddick/geoffrey/modules/geoffrey" - "github.com/jriddick/geoffrey/modules/plugin" - "github.com/yuin/gluamapper" - "github.com/yuin/gopher-lua" -) - -var ( - sigs = make(chan os.Signal, 1) - bots *geoffrey.Geoffrey - wg sync.WaitGroup ) func init() { @@ -30,85 +12,8 @@ func init() { // Set the log level to debug log.SetLevel(log.DebugLevel) - - // Capture signals - signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM, syscall.SIGKILL) - - go func() { - // Wait until we get a signal - <-sigs - - // Shutdown the bot - bots.Shutdown() - - // Exit the program - wg.Done() - }() -} - -type config struct { - PluginFolder string - LogLevel uint8 } func main() { - state := lua.NewState(lua.Options{ - SkipOpenLibs: false, - }) - - // Close the Lua VM when we are done - defer state.Close() - - // Remove unsafe modules - state.DoString("coroutine=nil;debug=nil;io=nil;os=nil") - - // Add the plugin module - plugins := plugin.NewPluginModule() - plugins.Register(state) - - // Add the geoffrey module - bots := geoffrey.NewGeoffrey(plugins) - bots.Register(state) - - // Load const.lua - if err := state.DoFile("const.lua"); err != nil { - log.WithError(err).Fatalln("Could not run const.lua") - } - - // Load config.lua - if err := state.DoFile("config.lua"); err != nil { - log.WithError(err).Fatalln("Could not run config.lua") - } - - // Map the configuration struct - var cfg config - if err := gluamapper.Map(state.GetGlobal("config").(*lua.LTable), &cfg); err != nil { - log.WithError(err).Fatalln("Could not parse configuration struct") - } - - // Change the log level - log.SetLevel(log.Level(cfg.LogLevel)) - - // Read all plugins - if files, err := ioutil.ReadDir(cfg.PluginFolder); err != nil { - log.WithError(err).Fatalf("Could not open plugin directory '%s'", cfg.PluginFolder) - } else { - for _, file := range files { - if !file.IsDir() { - if err := state.DoFile(fmt.Sprintf("%s/%s", cfg.PluginFolder, file.Name())); err != nil { - log.WithError(err).Errorf("Could not run file '%s'", file.Name()) - } - } - } - } - - // Load geoffrey.lua - if err := state.DoFile("geoffrey.lua"); err != nil { - log.WithError(err).Fatalln("Could not run geoffrey.lua") - } - log.Infoln("Geoffrey is now running...") - - wg.Add(1) - wg.Wait() } diff --git a/geoffrey.lua b/geoffrey.lua deleted file mode 100644 index 83cc032..0000000 --- a/geoffrey.lua +++ /dev/null @@ -1,32 +0,0 @@ --- Add a bot -geoffrey.add("geoffrey", { - Registration = { - Nick = "geoffrey", - User = "geoffrey", - Name = "geoffrey", - }, - Authentication = { - Username = "geoffrey", - Password = "...", - }, - Limits = { - Reconnect = 5, - Timeout = 5, - }, - Connection = { - Host = "localhost", - Port = 6667, - Secure = false, - InsecureSkipVerify = false, - Timeout = 30 - }, - Channels = { - "#geoffrey" - }, - Plugins = { - "echo", - "registration", - "join", - "ping" - }, -}) \ No newline at end of file diff --git a/glide.lock b/glide.lock index 86324eb..ebef7aa 100644 --- a/glide.lock +++ b/glide.lock @@ -1,12 +1,10 @@ hash: 45063f75224f26886556f8e26c469a6e83aa4db106cc0caf09273b389148af5a -updated: 2016-11-08T18:17:54.4531031+01:00 +updated: 2017-06-17T12:29:46.8655428+02:00 imports: - name: github.com/bndr/gopencils version: 102f2a4200dcd5b943fcd09fe0098cae05f3b627 -- name: github.com/mitchellh/mapstructure - version: f3009df150dadf309fdee4a54ed65c124afad715 - name: github.com/Sirupsen/logrus - version: d26492970760ca5d33129d2d799e34be5c4782eb + version: ba1b36c82c5e05c4f912a88eab0dcd91a171688f - name: github.com/smartystreets/goconvey version: d4c757aa9afd1e2fc1832aaab209b5794eb336e1 subpackages: @@ -32,43 +30,8 @@ testImports: - js - name: github.com/jtolds/gls version: 8ddce2a84170772b95dd5d576c48d517b22cac63 -- name: github.com/onsi/ginkgo - version: a8ccd817611666211fdf6e6a752174a0db8374a8 - subpackages: - - config - - internal/codelocation - - internal/containernode - - internal/failer - - internal/leafnodes - - internal/remote - - internal/spec - - internal/specrunner - - internal/suite - - internal/testingtproxy - - internal/writer - - reporters - - reporters/stenographer - - reporters/stenographer/support/go-colorable - - reporters/stenographer/support/go-isatty - - types -- name: github.com/onsi/gomega - version: d6ea11462a5e887f44c322f3c8cdda78d5a05117 - subpackages: - - format - - internal/assertion - - internal/asyncassertion - - internal/oraclematcher - - internal/testingtsupport - - matchers - - matchers/support/goraph/bipartitegraph - - matchers/support/goraph/edge - - matchers/support/goraph/node - - matchers/support/goraph/util - - types - name: github.com/smartystreets/assertions version: 2063fd1cc7c975db70502811a34b06ad034ccdf2 subpackages: - internal/go-render/render - internal/oglematchers -- name: gopkg.in/yaml.v2 - version: a5b47d31c556af34a302ce5d659e6fea44d90de0 diff --git a/helper/binding.go b/helper/binding.go deleted file mode 100644 index dfb3d40..0000000 --- a/helper/binding.go +++ /dev/null @@ -1,45 +0,0 @@ -package helper - -import ( - log "github.com/Sirupsen/logrus" - lua "github.com/yuin/gopher-lua" -) - -// GetUserData will check for and return LUserData on pos -// n on the Lua stack. If not found or if a different type -// it will return nil. -func GetUserData(n int, state *lua.LState) *lua.LUserData { - val := state.Get(n) - - if val.Type() != lua.LTUserData { - log.WithField("file", state.Where(1)).Errorf("Expected userdata but we got '%s'", val.Type().String()) - return nil - } - - return val.(*lua.LUserData) -} - -// GetString will check for and return LString on pos -// n on the Lua stack. It will return nil if not found. -func GetString(n int, state *lua.LState) *string { - val := state.Get(n) - - if val.Type() != lua.LTString { - log.WithField("file", state.Where(1)).Errorf("Expected string but we got '%s'", val.Type().String()) - return nil - } - - res := lua.LVAsString(val) - return &res -} - -// HasArguments will check if there are n amount of arguments -// on the Lua stack. If there is more ore less arguments we return false. -func HasArguments(n int, state *lua.LState) bool { - if state.GetTop() != n { - log.WithField("file", state.Where(1)).Errorf("Expected %d arguments but we got '%d'", n, state.GetTop()) - return false - } - - return true -} diff --git a/bot/bot.go b/helper/bot/bot.go similarity index 63% rename from bot/bot.go rename to helper/bot/bot.go index 6e74d79..d49df74 100644 --- a/bot/bot.go +++ b/helper/bot/bot.go @@ -9,7 +9,6 @@ import ( log "github.com/Sirupsen/logrus" "github.com/jriddick/geoffrey/irc" "github.com/jriddick/geoffrey/msg" - "github.com/yuin/gopher-lua" ) // MessageHandler is the function type for @@ -18,17 +17,15 @@ type MessageHandler func(*Bot, string) // Bot is the structure for an IRC bot type Bot struct { - client *irc.IRC - writer chan<- string - reader <-chan *msg.Message - stop chan struct{} - config Config - LuaHandlers map[string][]*lua.LFunction - state *lua.LState + client *irc.IRC + writer chan<- string + reader <-chan *msg.Message + stop chan struct{} + config Config } // NewBot creates a new bot -func NewBot(config Config, state *lua.LState) *Bot { +func NewBot(config Config) *Bot { // Create the bot bot := &Bot{ client: irc.NewIRC(irc.Config{ @@ -39,17 +36,10 @@ func NewBot(config Config, state *lua.LState) *Bot { Timeout: time.Second * time.Duration(config.Timeout), TimeoutLimit: config.TimeoutLimit, }), - config: config, - stop: make(chan struct{}), - LuaHandlers: make(map[string][]*lua.LFunction), - state: state, + config: config, + stop: make(chan struct{}), } - // Register the bot struct - RegisterBot(state) - RegisterConfig(state) - RegisterMessage(state) - return bot } @@ -81,34 +71,6 @@ func (b *Bot) Handler() { case msg := <-b.reader: // Log all messages log.Debugln(msg.String()) - - // Go through all Lua handlers - go func(bot *Bot, state *lua.LState) { - for _, handler := range bot.LuaHandlers[msg.Command] { - // Run the Lua handler - go func(state *lua.LState, handler *lua.LFunction, bot *Bot) { - // Push the handler function - state.Push(handler) - - // Create the metatable for our bot - value := state.NewUserData() - value.Value = bot - state.SetMetatable(value, state.GetTypeMetatable("bot")) - - // Push the bot - state.Push(value) - - // Push the message - PushMessage(msg, state) - - // Call the function - state.Call(2, 0) - - // Close the thread - state.Close() - }(state.NewThread(), handler, bot) - } - }(b, b.state.NewThread()) } } } @@ -160,11 +122,6 @@ func (b *Bot) User(user, name string) { b.writer <- "USER " + user + " 0 * :" + name } -// AddLuaHandler registers a Lua handler for the OnMessage event -func (b *Bot) AddLuaHandler(command string, handler *lua.LFunction) { - b.LuaHandlers[command] = append(b.LuaHandlers[command], handler) -} - // Close will close the bot func (b *Bot) Close() { close(b.stop) diff --git a/bot/config.go b/helper/bot/config.go similarity index 100% rename from bot/config.go rename to helper/bot/config.go diff --git a/modules/geoffrey/geoffrey.go b/modules/geoffrey/geoffrey.go deleted file mode 100644 index 02a2918..0000000 --- a/modules/geoffrey/geoffrey.go +++ /dev/null @@ -1,155 +0,0 @@ -package geoffrey - -import ( - log "github.com/Sirupsen/logrus" - "github.com/jriddick/geoffrey/bot" - "github.com/jriddick/geoffrey/irc" - "github.com/jriddick/geoffrey/modules/plugin" - "github.com/yuin/gluamapper" - "github.com/yuin/gopher-lua" -) - -var ( - bots = make(map[string]*bot.Bot) -) - -// Geoffrey module handles the creation, start, stop and -// cleanup of bots. -type Geoffrey struct { - plugins *plugin.Plugin -} - -// Config is the configuration struct for Geoffrey -type Config struct { - Connection struct { - Host string - Port int - Secure bool - InsecureSkipVerify bool - Timeout int - } - Limits struct { - Reconnect int - Timeout int - } - Authentication struct { - Username string - Password string - } - Registration struct { - Nick string - User string - Name string - } - Channels []string - Plugins []string -} - -// NewGeoffrey returns a new Geoffrey module -func NewGeoffrey(plugins *plugin.Plugin) *Geoffrey { - return &Geoffrey{ - plugins: plugins, - } -} - -// Register will register the module to the lua state -func (g *Geoffrey) Register(L *lua.LState) { - L.RegisterModule("geoffrey", map[string]lua.LGFunction{ - "add": g.Add, - }) -} - -// Shutdown will stop all running bots -func (g *Geoffrey) Shutdown() { - for _, bot := range bots { - bot.Close() - } -} - -// Add will create and start a new bot -func (g *Geoffrey) Add(state *lua.LState) int { - // Build the logger - logger := log.WithField("file", state.Where(1)) - - // Check so we got the required number of parameters - if state.GetTop() != 2 { - logger.Errorf("Geoffrey:Add takes two parameters, we got %d", state.GetTop()) - return 0 - } - - // Get the table - if state.Get(2).Type() != lua.LTTable { - logger.Errorf("Geoffrey:Add takes a table as a second parameter, we got '%s'", state.Get(2).Type().String()) - return 0 - } - table := state.Get(2).(*lua.LTable) - - // Get the name - if state.Get(1).Type() != lua.LTString { - logger.Errorf("Geoffrey:Add takes a string as the first parameter, we got '%s'", state.Get(1).Type().String()) - return 0 - } - name := lua.LVAsString(state.Get(1)) - - // The bot configuration - var config Config - - // Map the configuration - if err := gluamapper.Map(table, &config); err != nil { - log.Fatalln(err) - } - - // Create the bot - bots[name] = bot.NewBot(bot.Config{ - Hostname: config.Connection.Host, - Port: config.Connection.Port, - Secure: config.Connection.Secure, - InsecureSkipVerify: config.Connection.InsecureSkipVerify, - Timeout: config.Connection.Timeout, - TimeoutLimit: config.Limits.Timeout, - ReconnectLimit: config.Limits.Reconnect, - Nick: config.Registration.Nick, - User: config.Registration.User, - Name: config.Registration.Name, - Channels: config.Channels, - }, state.NewThread()) - - // Get all loaded plugins - for _, pluginName := range config.Plugins { - if plugin, ok := g.plugins.Plugins[pluginName]; !ok { - logger.Errorf("Tried to use non-existent plugin '%s'", pluginName) - continue - } else { - for event, handler := range plugin.Bind { - switch event { - case "OnMessage": - event = irc.Message - case "OnPing": - event = irc.Ping - case "OnWelcome": - event = irc.Welcome - case "OnJoin": - event = irc.Join - case "OnPart": - event = irc.Part - case "OnNameList": - event = irc.Namreply - case "OnNotice": - event = irc.Notice - } - - bots[name].AddLuaHandler(event, handler) - } - } - } - - // Connect - if err := bots[name].Connect(); err != nil { - logger.WithError(err).Errorln("We could not connect to the server") - } - - // Run the handler - go bots[name].Handler() - - return 0 -} diff --git a/modules/plugin/plugin.go b/modules/plugin/plugin.go deleted file mode 100644 index cf4a361..0000000 --- a/modules/plugin/plugin.go +++ /dev/null @@ -1,103 +0,0 @@ -package plugin - -import ( - log "github.com/Sirupsen/logrus" - "github.com/yuin/gluamapper" - "github.com/yuin/gopher-lua" -) - -// Plugin module handles the registration -// and management of plugins. -type Plugin struct { - Plugins map[string]luaPlugin - help map[string]string -} - -type luaPlugin struct { - Name string - Description string - Help string - Bind map[string]*lua.LFunction -} - -// NewPluginModule returns a new plugin module -func NewPluginModule() *Plugin { - return &Plugin{ - Plugins: make(map[string]luaPlugin), - help: make(map[string]string), - } -} - -// Register will register the plugin module to -// the given lua state. -func (p *Plugin) Register(state *lua.LState) { - state.PreloadModule("plugin", p.loader) -} - -func (p *Plugin) loader(state *lua.LState) int { - // Bind the functions to the module - module := state.SetFuncs(state.NewTable(), map[string]lua.LGFunction{ - "add": p.Add, - "help": p.Help, - }) - - // Push the module, exposing it to the Lua state - state.Push(module) - - return 1 -} - -// Add will add a new plugin to the system -func (p *Plugin) Add(state *lua.LState) int { - // Build the logger - logger := log.WithField("file", state.Where(1)) - - // Check so we get the required number of parameters - if state.GetTop() != 1 { - logger.Errorf("Plugin:Add takes one parameter, we got '%d'", state.GetTop()) - return 0 - } - - // Get the table - if state.Get(1).Type() != lua.LTTable { - logger.Errorf("Geoffrey:Add takes table as a parameter, we got '%s'", state.Get(1).Type().String()) - return 0 - } - table := state.Get(1).(*lua.LTable) - - // The registered plugin - var plugin luaPlugin - - // Map the table - if err := gluamapper.Map(table, &plugin); err != nil { - logger.WithError(err).Errorln("Could not parse the plugin") - return 0 - } - - if _, ok := p.Plugins[plugin.Name]; ok { - logger.Errorf("Plugin with name '%s' already exist", plugin.Name) - return 0 - } - - p.Plugins[plugin.Name] = plugin - - if plugin.Help != "" { - p.help[plugin.Name] = plugin.Help - } - - logger.Infof("Registered plugin '%s'", plugin.Name) - - return 0 -} - -// Help will return the help string for the given function -// if it exists. -func (p *Plugin) Help(state *lua.LState) int { - if val, ok := p.help[state.ToString(-1)]; ok && val != "" { - state.Push(lua.LString(val)) - } else { - state.Push(lua.LString("No help exists for that function")) - } - - return 1 -} diff --git a/plugins/echo.lua b/plugins/echo.lua deleted file mode 100644 index 4a6fe45..0000000 --- a/plugins/echo.lua +++ /dev/null @@ -1,17 +0,0 @@ -local plugin = require('plugin') - -local echo = { - Name = "echo", - Desciption = "Echoes everything it hears", - Bind = { - OnMessage = function (bot, msg) - if msg.Params[1] == bot.config.Nick then - bot:send(msg.Prefix.Name, msg.Trailing) - else - bot:send(msg.Params[1], msg.Trailing) - end - end - } -} - -plugin.add(echo) \ No newline at end of file diff --git a/plugins/join.lua b/plugins/join.lua deleted file mode 100644 index 569a593..0000000 --- a/plugins/join.lua +++ /dev/null @@ -1,15 +0,0 @@ -local plugin = require('plugin') - -local join = { - Name = "join", - Description = "Join will join all pre-defined channels", - Bind = { - OnWelcome = function (bot, msg) - for key, value in pairs(bot.config.Channels) do - bot:join(value) - end - end - } -} - -plugin.add(join) \ No newline at end of file diff --git a/plugins/ping.lua b/plugins/ping.lua deleted file mode 100644 index b8f8faf..0000000 --- a/plugins/ping.lua +++ /dev/null @@ -1,13 +0,0 @@ -local plugin = require('plugin') - -local ping = { - Name = "ping", - Description = "Ping responds to pings", - Bind = { - OnPing = function (bot, msg) - bot:pong(msg.Trailing) - end - } -} - -plugin.add(ping) \ No newline at end of file diff --git a/plugins/registration.lua b/plugins/registration.lua deleted file mode 100644 index 1ca5587..0000000 --- a/plugins/registration.lua +++ /dev/null @@ -1,16 +0,0 @@ -local plugin = require('plugin') - -local registration = { - Name = "registration", - Description = "Registers nick and user when connecting", - Bind = { - OnNotice = function (bot, msg) - if msg.Trailing == "*** Looking up your hostname..." then - bot:nick(bot.config.Nick) - bot:user(bot.config.User, bot.config.Name) - end - end - } -} - -plugin.add(registration) \ No newline at end of file From 06bf018b4c23992a8fd8e6f8a7e6d07184721cc3 Mon Sep 17 00:00:00 2001 From: jriddick Date: Sat, 17 Jun 2017 12:45:57 +0200 Subject: [PATCH 2/2] Add simple example Add simple example that shows how to use the bot without Lua. --- {helper/bot => bot}/bot.go | 0 {helper/bot => bot}/config.go | 0 geoffrey.go | 49 +++++++++++++++++++++++++++++++++++ 3 files changed, 49 insertions(+) rename {helper/bot => bot}/bot.go (100%) rename {helper/bot => bot}/config.go (100%) diff --git a/helper/bot/bot.go b/bot/bot.go similarity index 100% rename from helper/bot/bot.go rename to bot/bot.go diff --git a/helper/bot/config.go b/bot/config.go similarity index 100% rename from helper/bot/config.go rename to bot/config.go diff --git a/geoffrey.go b/geoffrey.go index 362b087..de4de8f 100644 --- a/geoffrey.go +++ b/geoffrey.go @@ -3,7 +3,18 @@ package main import ( "os" + "sync" + + "os/signal" + "syscall" + log "github.com/Sirupsen/logrus" + "github.com/jriddick/geoffrey/bot" +) + +var ( + signals = make(chan os.Signal, 1) + wait sync.WaitGroup ) func init() { @@ -12,8 +23,46 @@ func init() { // Set the log level to debug log.SetLevel(log.DebugLevel) + + // Get signals + signal.Notify(signals, syscall.SIGINT, syscall.SIGTERM, syscall.SIGKILL) + + go func() { + // Wait until signal + <-signals + + // Let the program exit + wait.Done() + }() } func main() { log.Infoln("Geoffrey is now running...") + + config := bot.Config{ + Hostname: "irc.oftc.net", + Port: 6697, + Secure: true, + InsecureSkipVerify: false, + Nick: "geoffrey", + User: "geoffrey", + Name: "geoffrey-bot", + Channels: []string{"#geoffrey-dev"}, + Timeout: 1000, + TimeoutLimit: 1000, + ReconnectLimit: 1000, + } + + bot := bot.NewBot(config) + + if err := bot.Connect(); err != nil { + log.Fatalf("Could not connect: %v\n", err) + } + + // Wait until we should exit + wait.Add(1) + wait.Wait() + + // Stop the bot + bot.Close() }