1// This program is free software: you can redistribute it and/or modify 2// it under the terms of the GNU Affero General Public License as 3// published by the Free Software Foundation, either version 3 of the 4// License, or (at your option) any later version. 5// 6// This program is distributed in the hope that it will be useful, but 7// WITHOUT ANY WARRANTY; without even the implied warranty of 8// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 9// Affero General Public License for more details. 10// 11// You should have received a copy of the GNU Affero General Public 12// License along with this program. If not, see <http://www.gnu.org/licenses/>. 13 14package modules 15 16import ( 17 "encoding/json" 18 "fmt" 19 "github.com/nmeum/marvin/irc" 20 "io/ioutil" 21 "os" 22 "path/filepath" 23 "strings" 24) 25 26type Module interface { 27 Name() string 28 Help() string 29 Load(*irc.Client) error 30 Defaults() 31} 32 33type ModuleSet struct { 34 client *irc.Client 35 modules []Module 36 configs string 37} 38 39func NewModuleSet(client *irc.Client, configs string) *ModuleSet { 40 return &ModuleSet{client: client, configs: configs} 41} 42 43func (m *ModuleSet) Register(module Module) { 44 m.modules = append(m.modules, module) 45} 46 47func (m *ModuleSet) LoadAll() error { 48 if err := os.MkdirAll(m.configs, 0755); err != nil { 49 return err 50 } 51 52 for _, module := range m.modules { 53 fn := fmt.Sprintf("%s.json", module.Name()) 54 fp := filepath.Join(m.configs, fn) 55 56 module.Defaults() 57 data, err := ioutil.ReadFile(fp) 58 if err == nil { 59 if err := json.Unmarshal(data, &module); err != nil { 60 return err 61 } 62 } else if !os.IsNotExist(err) { 63 return err 64 } 65 66 if err := module.Load(m.client); err != nil { 67 return err 68 } 69 } 70 71 m.client.CmdHook("privmsg", m.helpCmd) 72 m.client.CmdHook("privmsg", m.moduleCmd) 73 m.client.CmdHook("privmsg", m.modulesCmd) 74 75 return nil 76} 77 78func (m *ModuleSet) findModule(name string) Module { 79 for _, module := range m.modules { 80 if module.Name() == name { 81 return module 82 } 83 } 84 85 return nil 86} 87 88func (m *ModuleSet) helpCmd(client *irc.Client, msg irc.Message) error { 89 if msg.Data != "!help" { 90 return nil 91 } 92 93 return client.Write("NOTICE %s :%s", msg.Receiver, 94 "Use !help MODULE to see the help message for the given module, use !modules to list all modules.") 95} 96 97func (m *ModuleSet) modulesCmd(client *irc.Client, msg irc.Message) error { 98 if msg.Data != "!modules" || len(m.modules) <= 0 { 99 return nil100 }101102 var names []string103 for _, module := range m.modules {104 names = append(names, module.Name())105 }106107 help := fmt.Sprintf("The following modules are available: %s",108 strings.Join(names, ", "))109110 return client.Write("NOTICE %s :%s", msg.Receiver, help)111}112113func (m *ModuleSet) moduleCmd(client *irc.Client, msg irc.Message) error {114 splited := strings.Fields(msg.Data)115 if len(splited) < 2 || splited[0] != "!help" {116 return nil117 }118119 name := strings.ToLower(splited[1])120 module := m.findModule(name)121 if module == nil {122 return client.Write("NOTICE %s :Module %q isn't installed",123 msg.Receiver, name)124 }125126 return client.Write("NOTICE %s :%s: %s",127 msg.Receiver, module.Name(), module.Help())128}