diff --git a/mattermost/server/bathroom-linux-amd64 b/mattermost/server/bathroom-linux-amd64 index bd4b98e..8473f7e 100755 --- a/mattermost/server/bathroom-linux-amd64 +++ b/mattermost/server/bathroom-linux-amd64 Binary files differ diff --git a/mattermost/server/bathroom-linux-amd64 b/mattermost/server/bathroom-linux-amd64 index bd4b98e..8473f7e 100755 --- a/mattermost/server/bathroom-linux-amd64 +++ b/mattermost/server/bathroom-linux-amd64 Binary files differ diff --git a/mattermost/server/bathroom.go b/mattermost/server/bathroom.go index d07f79d..043d702 100644 --- a/mattermost/server/bathroom.go +++ b/mattermost/server/bathroom.go @@ -4,6 +4,7 @@ "fmt" "net/http" "github.com/mattermost/mattermost-server/plugin" + "github.com/mattermost/mattermost-server/model" "github.com/pkg/errors" "sync" "reflect" @@ -13,11 +14,17 @@ "github.com/hashicorp/go-multierror" "github.com/kr/pretty" "strings" + "regexp" + "strconv" ) +var userSplit *regexp.Regexp = regexp.MustCompile(`\s+(^|[^,])|\s*,\s*`) + type Config struct { - NumDoors uint8 `json:",string"` + NumDoors string WatchPath string + AdminUsers string + numDoors uint8 } func (c *Config) configMap() map[string]interface{} { @@ -30,24 +37,26 @@ return lowerConfigMap } -type HelloWorldPlugin struct { +type BathroomMonitorPlugin struct { plugin.MattermostPlugin config *Config + adminUsers []string configLock sync.RWMutex configChanged chan struct{} doors map[uint8]bool configUpdates int + lastReport *string } -func (p *HelloWorldPlugin) initDoors() { +func (p *BathroomMonitorPlugin) initDoors() { p.doors = make(map[uint8]bool) - for i := uint8(0); i < p.config.NumDoors; i++ { + for i := uint8(0); i < p.config.numDoors; i++ { p.doors[i] = false } } -func (p *HelloWorldPlugin) init() *HelloWorldPlugin { - p.config = &Config{NumDoors: 1, WatchPath: "./"} +func (p *BathroomMonitorPlugin) init() *BathroomMonitorPlugin { + p.config = &Config{NumDoors: "1", WatchPath: "./", numDoors: 1, AdminUsers:""} p.configChanged = make(chan struct{}) p.initDoors() @@ -55,18 +64,18 @@ return p; } -func (p *HelloWorldPlugin) ServeHTTP(c *plugin.Context, w http.ResponseWriter, r *http.Request) { +func (p *BathroomMonitorPlugin) ServeHTTP(c *plugin.Context, w http.ResponseWriter, r *http.Request) { fmt.Fprint(w, "Hello, world!") } -func (p *HelloWorldPlugin) confChangedEvent() { +func (p *BathroomMonitorPlugin) confChangedEvent() { select { case p.configChanged <- struct{}{}: default: } } -func (p *HelloWorldPlugin) checkCorrectConfig() { +func (p *BathroomMonitorPlugin) checkCorrectConfig() { var currentConfig map[string]interface{} = p.getLowerCasePluginConfig() var goodConfig map[string]interface{} = p.config.configMap() if !cmp.Equal(currentConfig, goodConfig) { @@ -75,7 +84,7 @@ } } -func (p *HelloWorldPlugin) getLowerCasePluginConfig() map[string]interface{} { +func (p *BathroomMonitorPlugin) getLowerCasePluginConfig() map[string]interface{} { var currentConfig map[string]interface{} = p.API.GetPluginConfig() var lowerConfig map[string]interface{} = make(map[string]interface{}) for k, v := range(currentConfig) { @@ -84,29 +93,88 @@ return lowerConfig } -func (p *HelloWorldPlugin) OnConfigurationChange() error { +func (p *BathroomMonitorPlugin) postAdminChannel(text string) { + p.API.LogError(text) + if p.lastReport != nil && *p.lastReport == text { + return + } + p.lastReport = &text + var users []*model.User = make([]*model.User, 0, len(p.adminUsers)) + for _, un := range(p.adminUsers) { + u, _ := p.API.GetUserByUsername(un) + if u != nil { + users = append(users, u) + } + } + + if len(users) > 0 { + admin := users[0] + bots, _ := p.API.GetBots(&model.BotGetOptions{Page:0, PerPage:1000}) + var bathroom_bot *model.Bot = nil + if bots != nil { + for _, b := range(bots) { + if b.Username == "bathroom-bot" { + bathroom_bot = b + break + } + } + } + + if bathroom_bot == nil { + created_bathroom_bot, err := p.API.CreateBot(&model.Bot{Username:"bathroom-bot", OwnerId:admin.Id, DisplayName:"Bathroom Bot", Description:"Tracks Bathroom Status"}) + if err != nil { + p.API.LogError(errors.Wrap(err, "Couldn't create bathroom-bot bot").Error()) + return + } + bathroom_bot = created_bathroom_bot + } + + if bathroom_bot == nil { + p.API.LogError("Really couldn't create bathroom-bot bot") + return + } + + for _, u := range(users) { + channel, err := p.API.GetDirectChannel(bathroom_bot.UserId, u.Id); + if err != nil { + p.API.LogError(errors.Wrap(err, fmt.Sprintf("Couldn't get direct channel to user %s", u.Username)).Error()) + continue + } + p.API.CreatePost(&model.Post{UserId: bathroom_bot.UserId, ChannelId:channel.Id, Message:text, MessageSource:text}) + } + } else { + p.API.LogError("No admin users?") + } +} + +func (p *BathroomMonitorPlugin) OnConfigurationChange() error { p.configLock.Lock() defer p.configLock.Unlock() - var currentConfig map[string]interface{} = p.getLowerCasePluginConfig() - if cmp.Equal(currentConfig, p.config.configMap()) { - p.API.LogInfo(fmt.Sprintf("%d: Skipping matching config", p.configUpdates)) - return nil - } + //var currentConfig map[string]interface{} = p.getLowerCasePluginConfig() + //if cmp.Equal(currentConfig, p.config.configMap()) { + // p.API.LogInfo(fmt.Sprintf("%d: Skipping matching config", p.configUpdates)) + // return nil + //} - defer p.checkCorrectConfig() + //defer p.checkCorrectConfig() var newConfig *Config = new(Config); if err := p.API.LoadPluginConfiguration(newConfig); err != nil { - return errors.Wrap(err, fmt.Sprintf("%d: Failed to load configuration", p.configUpdates)) + newErr := errors.Wrap(err, fmt.Sprintf("%d: Failed to load configuration", p.configUpdates)) + p.postAdminChannel(newErr.Error()) + return newErr } - if newConfig == p.config || reflect.ValueOf(*newConfig).NumField() == 0 || cmp.Equal(*newConfig, *p.config) { + //p.API.LogInfo(fmt.Sprintf("Loaded %t %t", newConfig != nil, p.config != nil)) + + if newConfig == nil || newConfig == p.config || reflect.ValueOf(*newConfig).NumField() == 0 { p.API.LogInfo("Passed same config, or empty?") return nil; } + //p.API.LogInfo("Checked dupe") var configErr error = nil if _, err := os.Stat(newConfig.WatchPath); err != nil { @@ -114,18 +182,45 @@ configErr = multierror.Append(configErr, errors.Wrap(err, "Invalid watch path")) } + //p.API.LogInfo("Checked path") + + numDoors, err := strconv.ParseUint(newConfig.NumDoors, 10, 8) + if err != nil { + //p.API.LogError("Bad doors! " + err.Error()) + newConfig.NumDoors = "1" + newConfig.numDoors = 1 + configErr = multierror.Append(configErr, errors.Wrap(err, "Invalid number of doors")) + } else { + //p.API.LogError(fmt.Sprintf("Good doors! %d", numDoors)) + newConfig.numDoors = uint8(numDoors) + } + p.config = newConfig + p.adminUsers = make([]string, 0, 4) + + split := userSplit.Split(newConfig.AdminUsers, -1) + for _, un := range split { + trimmed := strings.Trim(un, ", \t\n") + if trimmed != "" { + p.adminUsers = append(p.adminUsers, trimmed) + } + } + p.configUpdates++ p.initDoors() - p.API.LogInfo(fmt.Sprintf("%d: Config: %d %s", p.configUpdates, p.config.NumDoors, p.config.WatchPath)) + p.API.LogInfo(fmt.Sprintf("%d: Config: %d %s", p.configUpdates, p.config.numDoors, p.config.WatchPath)) + + if configErr != nil { + p.postAdminChannel(configErr.Error()) + } return configErr } -func watchLoop(p *HelloWorldPlugin) { +func watchLoop(p *BathroomMonitorPlugin) { for { p.configLock.Lock() p.configLock.Unlock() @@ -137,13 +232,11 @@ } -func (p *HelloWorldPlugin) OnActivate() error { +func (p *BathroomMonitorPlugin) OnActivate() error { go watchLoop(p) return nil } -// This example demonstrates a plugin that handles HTTP requests which respond by greeting the -// world. func main() { - plugin.ClientMain((&HelloWorldPlugin{}).init()) + plugin.ClientMain((&BathroomMonitorPlugin{}).init()) } diff --git a/mattermost/server/bathroom-linux-amd64 b/mattermost/server/bathroom-linux-amd64 index bd4b98e..8473f7e 100755 --- a/mattermost/server/bathroom-linux-amd64 +++ b/mattermost/server/bathroom-linux-amd64 Binary files differ diff --git a/mattermost/server/bathroom.go b/mattermost/server/bathroom.go index d07f79d..043d702 100644 --- a/mattermost/server/bathroom.go +++ b/mattermost/server/bathroom.go @@ -4,6 +4,7 @@ "fmt" "net/http" "github.com/mattermost/mattermost-server/plugin" + "github.com/mattermost/mattermost-server/model" "github.com/pkg/errors" "sync" "reflect" @@ -13,11 +14,17 @@ "github.com/hashicorp/go-multierror" "github.com/kr/pretty" "strings" + "regexp" + "strconv" ) +var userSplit *regexp.Regexp = regexp.MustCompile(`\s+(^|[^,])|\s*,\s*`) + type Config struct { - NumDoors uint8 `json:",string"` + NumDoors string WatchPath string + AdminUsers string + numDoors uint8 } func (c *Config) configMap() map[string]interface{} { @@ -30,24 +37,26 @@ return lowerConfigMap } -type HelloWorldPlugin struct { +type BathroomMonitorPlugin struct { plugin.MattermostPlugin config *Config + adminUsers []string configLock sync.RWMutex configChanged chan struct{} doors map[uint8]bool configUpdates int + lastReport *string } -func (p *HelloWorldPlugin) initDoors() { +func (p *BathroomMonitorPlugin) initDoors() { p.doors = make(map[uint8]bool) - for i := uint8(0); i < p.config.NumDoors; i++ { + for i := uint8(0); i < p.config.numDoors; i++ { p.doors[i] = false } } -func (p *HelloWorldPlugin) init() *HelloWorldPlugin { - p.config = &Config{NumDoors: 1, WatchPath: "./"} +func (p *BathroomMonitorPlugin) init() *BathroomMonitorPlugin { + p.config = &Config{NumDoors: "1", WatchPath: "./", numDoors: 1, AdminUsers:""} p.configChanged = make(chan struct{}) p.initDoors() @@ -55,18 +64,18 @@ return p; } -func (p *HelloWorldPlugin) ServeHTTP(c *plugin.Context, w http.ResponseWriter, r *http.Request) { +func (p *BathroomMonitorPlugin) ServeHTTP(c *plugin.Context, w http.ResponseWriter, r *http.Request) { fmt.Fprint(w, "Hello, world!") } -func (p *HelloWorldPlugin) confChangedEvent() { +func (p *BathroomMonitorPlugin) confChangedEvent() { select { case p.configChanged <- struct{}{}: default: } } -func (p *HelloWorldPlugin) checkCorrectConfig() { +func (p *BathroomMonitorPlugin) checkCorrectConfig() { var currentConfig map[string]interface{} = p.getLowerCasePluginConfig() var goodConfig map[string]interface{} = p.config.configMap() if !cmp.Equal(currentConfig, goodConfig) { @@ -75,7 +84,7 @@ } } -func (p *HelloWorldPlugin) getLowerCasePluginConfig() map[string]interface{} { +func (p *BathroomMonitorPlugin) getLowerCasePluginConfig() map[string]interface{} { var currentConfig map[string]interface{} = p.API.GetPluginConfig() var lowerConfig map[string]interface{} = make(map[string]interface{}) for k, v := range(currentConfig) { @@ -84,29 +93,88 @@ return lowerConfig } -func (p *HelloWorldPlugin) OnConfigurationChange() error { +func (p *BathroomMonitorPlugin) postAdminChannel(text string) { + p.API.LogError(text) + if p.lastReport != nil && *p.lastReport == text { + return + } + p.lastReport = &text + var users []*model.User = make([]*model.User, 0, len(p.adminUsers)) + for _, un := range(p.adminUsers) { + u, _ := p.API.GetUserByUsername(un) + if u != nil { + users = append(users, u) + } + } + + if len(users) > 0 { + admin := users[0] + bots, _ := p.API.GetBots(&model.BotGetOptions{Page:0, PerPage:1000}) + var bathroom_bot *model.Bot = nil + if bots != nil { + for _, b := range(bots) { + if b.Username == "bathroom-bot" { + bathroom_bot = b + break + } + } + } + + if bathroom_bot == nil { + created_bathroom_bot, err := p.API.CreateBot(&model.Bot{Username:"bathroom-bot", OwnerId:admin.Id, DisplayName:"Bathroom Bot", Description:"Tracks Bathroom Status"}) + if err != nil { + p.API.LogError(errors.Wrap(err, "Couldn't create bathroom-bot bot").Error()) + return + } + bathroom_bot = created_bathroom_bot + } + + if bathroom_bot == nil { + p.API.LogError("Really couldn't create bathroom-bot bot") + return + } + + for _, u := range(users) { + channel, err := p.API.GetDirectChannel(bathroom_bot.UserId, u.Id); + if err != nil { + p.API.LogError(errors.Wrap(err, fmt.Sprintf("Couldn't get direct channel to user %s", u.Username)).Error()) + continue + } + p.API.CreatePost(&model.Post{UserId: bathroom_bot.UserId, ChannelId:channel.Id, Message:text, MessageSource:text}) + } + } else { + p.API.LogError("No admin users?") + } +} + +func (p *BathroomMonitorPlugin) OnConfigurationChange() error { p.configLock.Lock() defer p.configLock.Unlock() - var currentConfig map[string]interface{} = p.getLowerCasePluginConfig() - if cmp.Equal(currentConfig, p.config.configMap()) { - p.API.LogInfo(fmt.Sprintf("%d: Skipping matching config", p.configUpdates)) - return nil - } + //var currentConfig map[string]interface{} = p.getLowerCasePluginConfig() + //if cmp.Equal(currentConfig, p.config.configMap()) { + // p.API.LogInfo(fmt.Sprintf("%d: Skipping matching config", p.configUpdates)) + // return nil + //} - defer p.checkCorrectConfig() + //defer p.checkCorrectConfig() var newConfig *Config = new(Config); if err := p.API.LoadPluginConfiguration(newConfig); err != nil { - return errors.Wrap(err, fmt.Sprintf("%d: Failed to load configuration", p.configUpdates)) + newErr := errors.Wrap(err, fmt.Sprintf("%d: Failed to load configuration", p.configUpdates)) + p.postAdminChannel(newErr.Error()) + return newErr } - if newConfig == p.config || reflect.ValueOf(*newConfig).NumField() == 0 || cmp.Equal(*newConfig, *p.config) { + //p.API.LogInfo(fmt.Sprintf("Loaded %t %t", newConfig != nil, p.config != nil)) + + if newConfig == nil || newConfig == p.config || reflect.ValueOf(*newConfig).NumField() == 0 { p.API.LogInfo("Passed same config, or empty?") return nil; } + //p.API.LogInfo("Checked dupe") var configErr error = nil if _, err := os.Stat(newConfig.WatchPath); err != nil { @@ -114,18 +182,45 @@ configErr = multierror.Append(configErr, errors.Wrap(err, "Invalid watch path")) } + //p.API.LogInfo("Checked path") + + numDoors, err := strconv.ParseUint(newConfig.NumDoors, 10, 8) + if err != nil { + //p.API.LogError("Bad doors! " + err.Error()) + newConfig.NumDoors = "1" + newConfig.numDoors = 1 + configErr = multierror.Append(configErr, errors.Wrap(err, "Invalid number of doors")) + } else { + //p.API.LogError(fmt.Sprintf("Good doors! %d", numDoors)) + newConfig.numDoors = uint8(numDoors) + } + p.config = newConfig + p.adminUsers = make([]string, 0, 4) + + split := userSplit.Split(newConfig.AdminUsers, -1) + for _, un := range split { + trimmed := strings.Trim(un, ", \t\n") + if trimmed != "" { + p.adminUsers = append(p.adminUsers, trimmed) + } + } + p.configUpdates++ p.initDoors() - p.API.LogInfo(fmt.Sprintf("%d: Config: %d %s", p.configUpdates, p.config.NumDoors, p.config.WatchPath)) + p.API.LogInfo(fmt.Sprintf("%d: Config: %d %s", p.configUpdates, p.config.numDoors, p.config.WatchPath)) + + if configErr != nil { + p.postAdminChannel(configErr.Error()) + } return configErr } -func watchLoop(p *HelloWorldPlugin) { +func watchLoop(p *BathroomMonitorPlugin) { for { p.configLock.Lock() p.configLock.Unlock() @@ -137,13 +232,11 @@ } -func (p *HelloWorldPlugin) OnActivate() error { +func (p *BathroomMonitorPlugin) OnActivate() error { go watchLoop(p) return nil } -// This example demonstrates a plugin that handles HTTP requests which respond by greeting the -// world. func main() { - plugin.ClientMain((&HelloWorldPlugin{}).init()) + plugin.ClientMain((&BathroomMonitorPlugin{}).init()) } diff --git a/mattermost/server/bathroom.tar.gz b/mattermost/server/bathroom.tar.gz index 89e81cb..d11c006 100644 --- a/mattermost/server/bathroom.tar.gz +++ b/mattermost/server/bathroom.tar.gz Binary files differ diff --git a/mattermost/server/bathroom-linux-amd64 b/mattermost/server/bathroom-linux-amd64 index bd4b98e..8473f7e 100755 --- a/mattermost/server/bathroom-linux-amd64 +++ b/mattermost/server/bathroom-linux-amd64 Binary files differ diff --git a/mattermost/server/bathroom.go b/mattermost/server/bathroom.go index d07f79d..043d702 100644 --- a/mattermost/server/bathroom.go +++ b/mattermost/server/bathroom.go @@ -4,6 +4,7 @@ "fmt" "net/http" "github.com/mattermost/mattermost-server/plugin" + "github.com/mattermost/mattermost-server/model" "github.com/pkg/errors" "sync" "reflect" @@ -13,11 +14,17 @@ "github.com/hashicorp/go-multierror" "github.com/kr/pretty" "strings" + "regexp" + "strconv" ) +var userSplit *regexp.Regexp = regexp.MustCompile(`\s+(^|[^,])|\s*,\s*`) + type Config struct { - NumDoors uint8 `json:",string"` + NumDoors string WatchPath string + AdminUsers string + numDoors uint8 } func (c *Config) configMap() map[string]interface{} { @@ -30,24 +37,26 @@ return lowerConfigMap } -type HelloWorldPlugin struct { +type BathroomMonitorPlugin struct { plugin.MattermostPlugin config *Config + adminUsers []string configLock sync.RWMutex configChanged chan struct{} doors map[uint8]bool configUpdates int + lastReport *string } -func (p *HelloWorldPlugin) initDoors() { +func (p *BathroomMonitorPlugin) initDoors() { p.doors = make(map[uint8]bool) - for i := uint8(0); i < p.config.NumDoors; i++ { + for i := uint8(0); i < p.config.numDoors; i++ { p.doors[i] = false } } -func (p *HelloWorldPlugin) init() *HelloWorldPlugin { - p.config = &Config{NumDoors: 1, WatchPath: "./"} +func (p *BathroomMonitorPlugin) init() *BathroomMonitorPlugin { + p.config = &Config{NumDoors: "1", WatchPath: "./", numDoors: 1, AdminUsers:""} p.configChanged = make(chan struct{}) p.initDoors() @@ -55,18 +64,18 @@ return p; } -func (p *HelloWorldPlugin) ServeHTTP(c *plugin.Context, w http.ResponseWriter, r *http.Request) { +func (p *BathroomMonitorPlugin) ServeHTTP(c *plugin.Context, w http.ResponseWriter, r *http.Request) { fmt.Fprint(w, "Hello, world!") } -func (p *HelloWorldPlugin) confChangedEvent() { +func (p *BathroomMonitorPlugin) confChangedEvent() { select { case p.configChanged <- struct{}{}: default: } } -func (p *HelloWorldPlugin) checkCorrectConfig() { +func (p *BathroomMonitorPlugin) checkCorrectConfig() { var currentConfig map[string]interface{} = p.getLowerCasePluginConfig() var goodConfig map[string]interface{} = p.config.configMap() if !cmp.Equal(currentConfig, goodConfig) { @@ -75,7 +84,7 @@ } } -func (p *HelloWorldPlugin) getLowerCasePluginConfig() map[string]interface{} { +func (p *BathroomMonitorPlugin) getLowerCasePluginConfig() map[string]interface{} { var currentConfig map[string]interface{} = p.API.GetPluginConfig() var lowerConfig map[string]interface{} = make(map[string]interface{}) for k, v := range(currentConfig) { @@ -84,29 +93,88 @@ return lowerConfig } -func (p *HelloWorldPlugin) OnConfigurationChange() error { +func (p *BathroomMonitorPlugin) postAdminChannel(text string) { + p.API.LogError(text) + if p.lastReport != nil && *p.lastReport == text { + return + } + p.lastReport = &text + var users []*model.User = make([]*model.User, 0, len(p.adminUsers)) + for _, un := range(p.adminUsers) { + u, _ := p.API.GetUserByUsername(un) + if u != nil { + users = append(users, u) + } + } + + if len(users) > 0 { + admin := users[0] + bots, _ := p.API.GetBots(&model.BotGetOptions{Page:0, PerPage:1000}) + var bathroom_bot *model.Bot = nil + if bots != nil { + for _, b := range(bots) { + if b.Username == "bathroom-bot" { + bathroom_bot = b + break + } + } + } + + if bathroom_bot == nil { + created_bathroom_bot, err := p.API.CreateBot(&model.Bot{Username:"bathroom-bot", OwnerId:admin.Id, DisplayName:"Bathroom Bot", Description:"Tracks Bathroom Status"}) + if err != nil { + p.API.LogError(errors.Wrap(err, "Couldn't create bathroom-bot bot").Error()) + return + } + bathroom_bot = created_bathroom_bot + } + + if bathroom_bot == nil { + p.API.LogError("Really couldn't create bathroom-bot bot") + return + } + + for _, u := range(users) { + channel, err := p.API.GetDirectChannel(bathroom_bot.UserId, u.Id); + if err != nil { + p.API.LogError(errors.Wrap(err, fmt.Sprintf("Couldn't get direct channel to user %s", u.Username)).Error()) + continue + } + p.API.CreatePost(&model.Post{UserId: bathroom_bot.UserId, ChannelId:channel.Id, Message:text, MessageSource:text}) + } + } else { + p.API.LogError("No admin users?") + } +} + +func (p *BathroomMonitorPlugin) OnConfigurationChange() error { p.configLock.Lock() defer p.configLock.Unlock() - var currentConfig map[string]interface{} = p.getLowerCasePluginConfig() - if cmp.Equal(currentConfig, p.config.configMap()) { - p.API.LogInfo(fmt.Sprintf("%d: Skipping matching config", p.configUpdates)) - return nil - } + //var currentConfig map[string]interface{} = p.getLowerCasePluginConfig() + //if cmp.Equal(currentConfig, p.config.configMap()) { + // p.API.LogInfo(fmt.Sprintf("%d: Skipping matching config", p.configUpdates)) + // return nil + //} - defer p.checkCorrectConfig() + //defer p.checkCorrectConfig() var newConfig *Config = new(Config); if err := p.API.LoadPluginConfiguration(newConfig); err != nil { - return errors.Wrap(err, fmt.Sprintf("%d: Failed to load configuration", p.configUpdates)) + newErr := errors.Wrap(err, fmt.Sprintf("%d: Failed to load configuration", p.configUpdates)) + p.postAdminChannel(newErr.Error()) + return newErr } - if newConfig == p.config || reflect.ValueOf(*newConfig).NumField() == 0 || cmp.Equal(*newConfig, *p.config) { + //p.API.LogInfo(fmt.Sprintf("Loaded %t %t", newConfig != nil, p.config != nil)) + + if newConfig == nil || newConfig == p.config || reflect.ValueOf(*newConfig).NumField() == 0 { p.API.LogInfo("Passed same config, or empty?") return nil; } + //p.API.LogInfo("Checked dupe") var configErr error = nil if _, err := os.Stat(newConfig.WatchPath); err != nil { @@ -114,18 +182,45 @@ configErr = multierror.Append(configErr, errors.Wrap(err, "Invalid watch path")) } + //p.API.LogInfo("Checked path") + + numDoors, err := strconv.ParseUint(newConfig.NumDoors, 10, 8) + if err != nil { + //p.API.LogError("Bad doors! " + err.Error()) + newConfig.NumDoors = "1" + newConfig.numDoors = 1 + configErr = multierror.Append(configErr, errors.Wrap(err, "Invalid number of doors")) + } else { + //p.API.LogError(fmt.Sprintf("Good doors! %d", numDoors)) + newConfig.numDoors = uint8(numDoors) + } + p.config = newConfig + p.adminUsers = make([]string, 0, 4) + + split := userSplit.Split(newConfig.AdminUsers, -1) + for _, un := range split { + trimmed := strings.Trim(un, ", \t\n") + if trimmed != "" { + p.adminUsers = append(p.adminUsers, trimmed) + } + } + p.configUpdates++ p.initDoors() - p.API.LogInfo(fmt.Sprintf("%d: Config: %d %s", p.configUpdates, p.config.NumDoors, p.config.WatchPath)) + p.API.LogInfo(fmt.Sprintf("%d: Config: %d %s", p.configUpdates, p.config.numDoors, p.config.WatchPath)) + + if configErr != nil { + p.postAdminChannel(configErr.Error()) + } return configErr } -func watchLoop(p *HelloWorldPlugin) { +func watchLoop(p *BathroomMonitorPlugin) { for { p.configLock.Lock() p.configLock.Unlock() @@ -137,13 +232,11 @@ } -func (p *HelloWorldPlugin) OnActivate() error { +func (p *BathroomMonitorPlugin) OnActivate() error { go watchLoop(p) return nil } -// This example demonstrates a plugin that handles HTTP requests which respond by greeting the -// world. func main() { - plugin.ClientMain((&HelloWorldPlugin{}).init()) + plugin.ClientMain((&BathroomMonitorPlugin{}).init()) } diff --git a/mattermost/server/bathroom.tar.gz b/mattermost/server/bathroom.tar.gz index 89e81cb..d11c006 100644 --- a/mattermost/server/bathroom.tar.gz +++ b/mattermost/server/bathroom.tar.gz Binary files differ diff --git a/mattermost/server/plugin.json b/mattermost/server/plugin.json index 51d6b8b..6158eed 100644 --- a/mattermost/server/plugin.json +++ b/mattermost/server/plugin.json @@ -7,7 +7,8 @@ "settings_schema": { "settings": [ {"key":"NumDoors", "display_name":"Number of Door Sensors", "type":"text", "default":"1", "help_text":"How many Pis"}, - {"key":"WatchPath", "display_name":"Pi status folder", "type":"text", "default":"./", "help_text":"Path to watch for doorX files updated from PHP"} + {"key":"WatchPath", "display_name":"Pi status folder", "type":"text", "default":"./", "help_text":"Path to watch for doorX files updated from PHP"}, + {"key":"AdminUsers", "display_name":"Plugin admin users", "type":"text", "default":"", "help_text":"Space- or comma-separated list of users to notify with plugin debug message"} ] } }