diff --git a/bot.go b/bot.go index 3b44556..4ee0e6a 100644 --- a/bot.go +++ b/bot.go @@ -3,6 +3,7 @@ package main import ( "encoding/json" "flag" + "fmt" "io/ioutil" "log" "strings" @@ -10,8 +11,9 @@ import ( ) type Config struct { - Token string `json:"token"` - Plugins map[string]string `json:"plugins"` + Token string `json:"token"` + Plugins map[string]string `json:"plugins"` + EnabledPlugins map[string]bool `json:"enabled"` } type Plugin interface { @@ -19,14 +21,16 @@ type Plugin interface { GetCommands() []string GetHelpText() []string GotCommand(string, Message, []string) + Setup() } var bot *BotApi var plugins []Plugin var config Config +var configPath *string func main() { - configPath := flag.String("config", "config.json", "path to config.json") + configPath = flag.String("config", "config.json", "path to config.json") flag.Parse() @@ -42,7 +46,34 @@ func main() { debug: true, }) - plugins = []Plugin{&HelpPlugin{}, &FAPlugin{}} + plugins = []Plugin{&HelpPlugin{}, &FAPlugin{}, &ManagePlugin{}} + + for _, plugin := range plugins { + val, ok := config.EnabledPlugins[plugin.GetName()] + + if !ok { + fmt.Printf("Enable '%s'? [y/N] ", plugin.GetName()) + + var enabled string + fmt.Scanln(&enabled) + + if strings.ToLower(enabled) == "y" { + plugin.Setup() + log.Printf("Plugin '%s' started!\n", plugin.GetName()) + + config.EnabledPlugins[plugin.GetName()] = true + } else { + config.EnabledPlugins[plugin.GetName()] = false + } + } + + if val { + plugin.Setup() + log.Printf("Plugin '%s' started!\n", plugin.GetName()) + } + + saveConfig() + } ticker := time.NewTicker(time.Second) @@ -66,16 +97,32 @@ func main() { } for _, plugin := range plugins { + val, _ := config.EnabledPlugins[plugin.GetName()] + if !val { + continue + } + parts := strings.Split(update.Message.Text, " ") + command := parts[0] for _, cmd := range plugin.GetCommands() { - if cmd == parts[0] { + if cmd == command { + if bot.config.debug { + log.Printf("'%s' matched plugin '%s'", update.Message.Text, plugin.GetName()) + } + args := append(parts[:0], parts[1:]...) - plugin.GotCommand(parts[0], update.Message, args) + plugin.GotCommand(command, update.Message, args) } } } } } } + +func saveConfig() { + data, _ := json.MarshalIndent(config, "", " ") + + ioutil.WriteFile(*configPath, data, 0600) +} diff --git a/methods.go b/methods.go index a385614..9238950 100644 --- a/methods.go +++ b/methods.go @@ -148,6 +148,14 @@ func (bot *BotApi) sendMessage(config MessageConfig) (Message, error) { if config.ReplyToMessageId != 0 { v.Add("reply_to_message_id", strconv.Itoa(config.ReplyToMessageId)) } + if config.ReplyMarkup != nil { + data, err := json.Marshal(config.ReplyMarkup) + if err != nil { + return Message{}, err + } + + v.Add("reply_markup", string(data)) + } resp, err := bot.makeRequest("sendMessage", v) if err != nil { @@ -623,6 +631,7 @@ type MessageConfig struct { Text string DisableWebPagePreview bool ReplyToMessageId int + ReplyMarkup interface{} } type ForwardConfig struct { diff --git a/plugin_fa.go b/plugin_fa.go new file mode 100644 index 0000000..253870a --- /dev/null +++ b/plugin_fa.go @@ -0,0 +1,99 @@ +package main + +import ( + "fmt" + "github.com/PuerkitoBio/goquery" + "github.com/ddliu/go-httpclient" + "io" + "net/http" + "os" + "strconv" + "strings" +) + +type FAPlugin struct { +} + +func (plugin *FAPlugin) GetName() string { + return "FA Mirrorer" +} + +func (plugin *FAPlugin) GetCommands() []string { + return []string{"/fa"} +} + +func (plugin *FAPlugin) GetHelpText() []string { + return []string{"/fa [link] - mirrors an image from FurAffinity"} +} + +func (plugin *FAPlugin) Setup() { + a, ok := config.Plugins["fa_a"] + if !ok { + fmt.Print("FurAffinity Cookie a: ") + fmt.Scanln(&a) + + config.Plugins["fa_a"] = a + } + + b, ok := config.Plugins["fa_b"] + if !ok { + fmt.Print("FurAffinity Cookie b: ") + fmt.Scanln(&b) + + config.Plugins["fa_b"] = b + } +} + +func (plugin *FAPlugin) GotCommand(command string, message Message, args []string) { + if len(args) == 0 { + bot.sendMessage(NewMessage(message.Chat.Id, "You need to include a link!")) + + return + } + + bot.sendChatAction(NewChatAction(message.Chat.Id, CHAT_UPLOAD_PHOTO)) + + _, err := strconv.Atoi(args[0]) + if err == nil { + args[0] = "http://www.furaffinity.net/view/" + args[0] + } + + resp, err := httpclient.WithCookie(&http.Cookie{ + Name: "b", + Value: config.Plugins["fa_b"], + }).WithCookie(&http.Cookie{ + Name: "a", + Value: config.Plugins["fa_a"], + }).Get(args[0], nil) + if err != nil { + bot.sendMessage(NewMessage(message.Chat.Id, "ERR : "+err.Error())) + } + + defer resp.Body.Close() + + doc, err := goquery.NewDocumentFromReader(resp.Body) + if err != nil { + bot.sendMessage(NewMessage(message.Chat.Id, "ERR : "+err.Error())) + } + + sel := doc.Find("#submissionImg") + for i := range sel.Nodes { + single := sel.Eq(i) + + val, _ := single.Attr("src") + + tokens := strings.Split(val, "/") + fileName := tokens[len(tokens)-1] + + output, _ := os.Create(fileName) + defer output.Close() + defer os.Remove(output.Name()) + + resp, _ := http.Get("http:" + val) + defer resp.Body.Close() + + io.Copy(output, resp.Body) + + bot.sendPhoto(NewPhotoUpload(message.Chat.Id, output.Name())) + } +} diff --git a/plugin_help.go b/plugin_help.go index 44770e1..25e95f1 100644 --- a/plugin_help.go +++ b/plugin_help.go @@ -20,6 +20,9 @@ func (plugin *HelpPlugin) GetHelpText() []string { return []string{"/help (/command) - returns help about a command"} } +func (plugin *HelpPlugin) Setup() { +} + func (plugin *HelpPlugin) GotCommand(command string, message Message, args []string) { msg := NewMessage(message.Chat.Id, "") msg.ReplyToMessageId = message.MessageId @@ -50,7 +53,12 @@ func (plugin *HelpPlugin) GotCommand(command string, message Message, args []str buffer.WriteString("\n\n") for _, plug := range plugins { + val, _ := config.EnabledPlugins[plugin.GetName()] + buffer.WriteString(plug.GetName()) + if !val { + buffer.WriteString(" (disabled)") + } buffer.WriteString("\n") for _, cmd := range plug.GetHelpText() { diff --git a/plugin_manage.go b/plugin_manage.go new file mode 100644 index 0000000..ed522c1 --- /dev/null +++ b/plugin_manage.go @@ -0,0 +1,153 @@ +package main + +import ( + "fmt" + "log" + "strings" +) + +type ManagePlugin struct { +} + +func (plugin *ManagePlugin) GetName() string { + return "Plugin manager" +} + +func (plugin *ManagePlugin) GetCommands() []string { + return []string{ + "/enable", + "Enable", + "/disable", + "Disable", + "/reload", + } +} + +func (plugin *ManagePlugin) GetHelpText() []string { + return []string{ + "/enable [name] - enables a plugin", + "/disable [name] - disables a plugin", + "/reload - reloads bot configuration", + } +} + +func (plugin *ManagePlugin) Setup() { +} + +func (plugin *ManagePlugin) GotCommand(command string, message Message, args []string) { + log.Println(command) + + if command == "/enable" { + keyboard := [][]string{} + + hasDisabled := false + for _, plug := range plugins { + enabled, _ := config.EnabledPlugins[plug.GetName()] + if enabled { + continue + } + + hasDisabled = true + keyboard = append(keyboard, []string{"Enable " + plug.GetName()}) + } + + if !hasDisabled { + msg := NewMessage(message.Chat.Id, "All plugins are enabled!") + msg.ReplyToMessageId = message.MessageId + + bot.sendMessage(msg) + + return + } + + msg := NewMessage(message.Chat.Id, "Please specify which plugin to enable") + msg.ReplyToMessageId = message.MessageId + msg.ReplyMarkup = ReplyKeyboardMarkup{ + Keyboard: keyboard, + OneTimeKeyboard: true, + Selective: true, + ResizeKeyboard: true, + } + + bot.sendMessage(msg) + } else if command == "Enable" { + pluginName := strings.SplitN(message.Text, " ", 2) + + msg := NewMessage(message.Chat.Id, "") + msg.ReplyToMessageId = message.MessageId + msg.ReplyMarkup = ReplyKeyboardHide{ + HideKeyboard: true, + Selective: true, + } + + _, ok := config.EnabledPlugins[pluginName[1]] + if !ok { + msg.Text = "Unknown plugin!" + msg.ReplyToMessageId = message.MessageId + bot.sendMessage(msg) + + return + } + + config.EnabledPlugins[pluginName[1]] = true + msg.Text = fmt.Sprintf("Enabled '%s'!", pluginName[1]) + bot.sendMessage(msg) + } else if command == "/disable" { + keyboard := [][]string{} + + hasEnabled := false + for _, plug := range plugins { + enabled, _ := config.EnabledPlugins[plug.GetName()] + if !enabled { + continue + } + + hasEnabled = true + keyboard = append(keyboard, []string{"Disable " + plug.GetName()}) + } + + if !hasEnabled { + msg := NewMessage(message.Chat.Id, "All plugins are disabled!") + msg.ReplyToMessageId = message.MessageId + + bot.sendMessage(msg) + + return + } + + msg := NewMessage(message.Chat.Id, "Please specify which plugin to disable") + msg.ReplyToMessageId = message.MessageId + msg.ReplyMarkup = ReplyKeyboardMarkup{ + Keyboard: keyboard, + OneTimeKeyboard: true, + Selective: true, + ResizeKeyboard: true, + } + + bot.sendMessage(msg) + } else if command == "Disable" { + pluginName := strings.SplitN(message.Text, " ", 2) + + msg := NewMessage(message.Chat.Id, "") + msg.ReplyToMessageId = message.MessageId + msg.ReplyMarkup = ReplyKeyboardHide{ + HideKeyboard: true, + Selective: true, + } + + _, ok := config.EnabledPlugins[pluginName[1]] + if !ok { + msg.Text = "Unknown plugin!" + msg.ReplyToMessageId = message.MessageId + bot.sendMessage(msg) + + return + } + + config.EnabledPlugins[pluginName[1]] = false + msg.Text = fmt.Sprintf("Disabled '%s'!", pluginName[1]) + bot.sendMessage(msg) + } + + saveConfig() +} diff --git a/responses.go b/responses.go index f2d3f4a..41fc76d 100644 --- a/responses.go +++ b/responses.go @@ -119,10 +119,10 @@ type UserProfilePhotos struct { } type ReplyKeyboardMarkup struct { - Keyboard map[string]map[string]string `json:"keyboard"` - ResizeKeyboard bool `json:"resize_keyboard"` - OneTimeKeyboard bool `json:"one_time_keyboard"` - Selective bool `json:"selective"` + Keyboard [][]string `json:"keyboard"` + ResizeKeyboard bool `json:"resize_keyboard"` + OneTimeKeyboard bool `json:"one_time_keyboard"` + Selective bool `json:"selective"` } type ReplyKeyboardHide struct {