plugin.go 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212
  1. package main
  2. import (
  3. "encoding/json"
  4. "github.com/girish17/op-mattermost-plugin/server/util"
  5. "github.com/gorilla/mux"
  6. "github.com/mattermost/mattermost-server/v5/model"
  7. "github.com/mattermost/mattermost-server/v5/plugin"
  8. "github.com/pkg/errors"
  9. "io/ioutil"
  10. "net/http"
  11. "path/filepath"
  12. "strings"
  13. "sync"
  14. )
  15. const opCommand = "op"
  16. const opBot = "op-mattermost"
  17. var pluginURL string
  18. // Plugin implements the interface expected by the Mattermost server to communicate between the server and plugin processes.
  19. type Plugin struct {
  20. plugin.MattermostPlugin
  21. // configurationLock synchronizes access to the configuration.
  22. configurationLock sync.RWMutex
  23. // configuration is the active plugin configuration. Consult getConfiguration and
  24. // setConfiguration for usage.
  25. configuration *configuration
  26. router *mux.Router
  27. }
  28. // ServeHTTP demonstrates a plugin that handles HTTP requests.
  29. func (p *Plugin) ServeHTTP(c *plugin.Context, w http.ResponseWriter, r *http.Request) {
  30. switch path := r.URL.Path; path {
  31. case "/opAuth":
  32. util.OpAuth(p.MattermostPlugin, w, r, pluginURL)
  33. break
  34. case "/createTimeLog":
  35. util.ShowSelProject(p.MattermostPlugin, w, r, pluginURL)
  36. break
  37. case "/projSel":
  38. util.WPHandler(p.MattermostPlugin, w, r, pluginURL)
  39. break
  40. case "/wpSel":
  41. util.LoadTimeLogDlg(p.MattermostPlugin, w, r, pluginURL)
  42. break
  43. case "/logTime":
  44. util.HandleSubmission(p.MattermostPlugin, w, r, pluginURL)
  45. break
  46. case "/getTimeLog":
  47. util.GetTimeLog(p.MattermostPlugin, w, r, pluginURL)
  48. break
  49. case "/delTimeLog":
  50. http.NotFound(w, r)
  51. break
  52. case "/createWP":
  53. http.NotFound(w, r)
  54. break
  55. case "/saveWP":
  56. http.NotFound(w, r)
  57. break
  58. case "/delWP":
  59. util.ShowDelWPSel(p.MattermostPlugin, w, r, pluginURL)
  60. break
  61. case "/bye":
  62. util.Logout(p.MattermostPlugin, w, r)
  63. break
  64. default:
  65. http.NotFound(w, r)
  66. }
  67. }
  68. // OnActivate See https://developers.mattermost.com/extend/plugins/server/reference/
  69. func (p *Plugin) OnActivate() error {
  70. if p.API.GetConfig().ServiceSettings.SiteURL == nil {
  71. p.API.LogError("SiteURL must be set. Some features will operate incorrectly if the SiteURL is not set. See documentation for details: http://about.mattermost.com/default-site-url")
  72. }
  73. if err := p.API.RegisterCommand(createOpCommand(p.GetSiteURL())); err != nil {
  74. return errors.Wrapf(err, "failed to register %s command", opCommand)
  75. }
  76. //if _, e := p.API.CreateBot(getBotModel(opBot)); e != nil {
  77. // return errors.Wrapf(e, "failed to create %s bot", opBot)
  78. //}
  79. return nil
  80. }
  81. func (p *Plugin) OnDeactivate() error {
  82. if e := p.API.PermanentDeleteBot(opBot); e != nil {
  83. return errors.Wrapf(e, "failed to permanently delete %s bot", opBot)
  84. }
  85. return nil
  86. }
  87. func (p *Plugin) ExecuteCommand(c *plugin.Context, args *model.CommandArgs) (*model.CommandResponse, *model.AppError) {
  88. siteURL := p.GetSiteURL()
  89. pluginURL = getPluginURL(siteURL)
  90. logoURL := getLogoURL(siteURL)
  91. p.API.LogDebug("Plugin URL :" + pluginURL)
  92. if opUserID, _ := p.API.KVGet(args.UserId); opUserID == nil {
  93. p.API.LogDebug("Creating interactive dialog...")
  94. util.OpenAuthDialog(p.MattermostPlugin, args.TriggerId, pluginURL, logoURL)
  95. resp := &model.CommandResponse{
  96. ResponseType: model.COMMAND_RESPONSE_TYPE_EPHEMERAL,
  97. Text: "opening op auth dialog",
  98. Username: opBot,
  99. IconURL: logoURL,
  100. }
  101. return resp, nil
  102. } else {
  103. cmd := args.Command
  104. cmdAction := strings.Split(cmd, " ")
  105. p.API.LogInfo("Command arg entered: " + cmdAction[1])
  106. opUserIDStr := string(opUserID)
  107. apiKeyStr := strings.Split(opUserIDStr, " ")
  108. opUrlStr := apiKeyStr[1]
  109. p.API.LogInfo("Retrieving from KV: opURL - " + opUrlStr + " apiKey - " + apiKeyStr[0])
  110. var cmdResp *model.CommandResponse
  111. client := &http.Client{}
  112. req, _ := http.NewRequest("GET", opUrlStr+"/api/v3/users/me", nil)
  113. req.SetBasicAuth("apikey", apiKeyStr[0])
  114. resp, _ := client.Do(req)
  115. opResBody, _ := ioutil.ReadAll(resp.Body)
  116. var opJsonRes map[string]string
  117. json.Unmarshal(opResBody, &opJsonRes)
  118. p.MattermostPlugin.API.LogDebug("Response from op-mattermost: ", opJsonRes["firstName"])
  119. var attachmentMap map[string]interface{}
  120. json.Unmarshal([]byte(util.GetAttachmentJSON(pluginURL)), &attachmentMap)
  121. cmdResp = &model.CommandResponse{
  122. ResponseType: model.COMMAND_RESPONSE_TYPE_IN_CHANNEL,
  123. Text: "Hello " + opJsonRes["name"] + " :)",
  124. Username: opBot,
  125. IconURL: logoURL,
  126. Props: attachmentMap,
  127. }
  128. return cmdResp, nil
  129. }
  130. }
  131. func (p *Plugin) GetSiteURL() string {
  132. siteURL := ""
  133. ptr := p.API.GetConfig().ServiceSettings.SiteURL
  134. if ptr != nil {
  135. siteURL = *ptr
  136. }
  137. return siteURL
  138. }
  139. func getLogoURL(siteURL string) string {
  140. return getPluginURL(siteURL) + "/public/op_logo.jpg"
  141. }
  142. func getPluginURL(siteURL string) string {
  143. return siteURL + "/plugins/" + manifest.Id
  144. }
  145. func createOpCommand(siteURL string) *model.Command {
  146. return &model.Command{
  147. Trigger: opCommand,
  148. Method: "POST",
  149. Username: opBot,
  150. IconURL: getLogoURL(siteURL),
  151. AutoComplete: true,
  152. AutoCompleteDesc: "Invoke OpenProject bot for Mattermost",
  153. AutoCompleteHint: "",
  154. DisplayName: opBot,
  155. Description: "OpenProject integration for Mattermost",
  156. URL: siteURL,
  157. }
  158. }
  159. func getBotModel(opBot string) *model.Bot {
  160. return &model.Bot{
  161. Username: opBot,
  162. DisplayName: opBot,
  163. Description: "OpenProject bot",
  164. }
  165. }
  166. func (p *Plugin) setBotIcon() {
  167. bundlePath, err := p.API.GetBundlePath()
  168. if err != nil {
  169. p.API.LogError("failed to get bundle path", err)
  170. }
  171. profileImage, err := ioutil.ReadFile(filepath.Join(bundlePath, "assets", "op_logo.svg"))
  172. if err != nil {
  173. p.API.LogError("failed to read profile image", err)
  174. }
  175. user, err := p.API.GetBot(opBot, false)
  176. if err != nil {
  177. p.API.LogError("failed to fetch bot user", err)
  178. }
  179. if appErr := p.API.SetBotIconImage(user.UserId, profileImage); appErr != nil {
  180. p.API.LogError("failed to set profile image", appErr)
  181. }
  182. }