diff --git a/README.md b/README.md index 1bcbf974b7..3f31f5332a 100644 --- a/README.md +++ b/README.md @@ -38,6 +38,7 @@ Minecraft server chat support via [MatterLink](https://github.com/elytra/MatterL * [Support multiple gateways(bridges) for your protocols](https://github.com/42wim/matterbridge/wiki/Features#support-multiple-gatewaysbridges-for-your-protocols) * [Message edits and deletes](https://github.com/42wim/matterbridge/wiki/Features#message-edits-and-deletes) * Preserves threading when possible +* Remote configuration files * [Attachment / files handling](https://github.com/42wim/matterbridge/wiki/Features#attachment--files-handling) * [Username and avatar spoofing](https://github.com/42wim/matterbridge/wiki/Features#username-and-avatar-spoofing) * [Private groups](https://github.com/42wim/matterbridge/wiki/Features#private-groups) diff --git a/bridge/api/api.go b/bridge/api/api.go index eef41a4a4d..ffdb3318e8 100644 --- a/bridge/api/api.go +++ b/bridge/api/api.go @@ -2,7 +2,9 @@ package api import ( "encoding/json" + "io/ioutil" "net/http" + "net/url" "sync" "time" @@ -41,7 +43,9 @@ func New(cfg *bridge.Config) bridge.Bridger { return key == b.GetString("Token"), nil })) } + e.GET("/api/health", b.handleHealthcheck) + e.PUT("/api/reload", b.handleConfigReload) e.GET("/api/messages", b.handleMessages) e.GET("/api/stream", b.handleStream) e.POST("/api/message", b.handlePostMessage) @@ -82,6 +86,40 @@ func (b *Api) handleHealthcheck(c echo.Context) error { return c.String(http.StatusOK, "OK") } +func (b *Api) handleConfigReload(c echo.Context) error { + cfgURL := b.GetString("ConfigURL") + if cfgURL == "" { + b.Log.Warning("Reload API triggered, but no config file url set.") + return c.String(http.StatusInternalServerError, "Internal Server Error") + } + + b.Log.Debugf("Reloading config from remote file: " + cfgURL) + _, err := url.ParseRequestURI(cfgURL) + if err != nil { + b.Log.Error("Malformed config file url: ", err) + return c.String(http.StatusInternalServerError, "Internal Server Error") + } + res, err := http.Get(cfgURL) + if err != nil { + b.Log.Error("Failed to fetch remote config file: ", err) + return c.String(http.StatusInternalServerError, "Internal Server Error") + } + defer res.Body.Close() + content, err := ioutil.ReadAll(res.Body) + if err != nil { + b.Log.Error("Error reading remote config file: ", err) + return c.String(http.StatusInternalServerError, "Internal Server Error") + } + cfgfile := b.Config.Bridge.Config.ConfigFileUsed() + err = ioutil.WriteFile(cfgfile, content, 0644) + if err != nil { + b.Log.Error("Failed to write remote config file: ", err) + return c.String(http.StatusInternalServerError, "Internal Server Error") + } + + return c.String(http.StatusAccepted, "Accepted") +} + func (b *Api) handlePostMessage(c echo.Context) error { message := config.Message{} if err := c.Bind(&message); err != nil { diff --git a/bridge/config/config.go b/bridge/config/config.go index bdf77f8820..a63c912ed8 100644 --- a/bridge/config/config.go +++ b/bridge/config/config.go @@ -66,6 +66,7 @@ type Protocol struct { Buffer int // api Charset string // irc ColorNicks bool // only irc for now + ConfigURL string // api Debug bool // general DebugLevel int // only for irc now EditSuffix string // mattermost, slack, discord, telegram, gitter @@ -229,6 +230,10 @@ func NewConfigFromString(input []byte) *Config { return mycfg } +func (c *Config) ConfigFileUsed() string { + return c.v.ConfigFileUsed() +} + func (c *Config) GetBool(key string) bool { c.RLock() defer c.RUnlock()