From f1d6d53036f36a066070df90f8efa7247e3322fc Mon Sep 17 00:00:00 2001 From: Tulir Asokan <tulir@maunium.net> Date: Sat, 30 Sep 2017 18:34:55 +0300 Subject: [PATCH] Add issue reading and save transaction IDs between sessions --- README.md | 2 +- command-handler.go | 10 +++--- commands.go | 83 ++++++++++++++++++++++++++++++++++++++-------- config.go | 9 ++--- matrix.go | 13 ++++++-- 5 files changed, 91 insertions(+), 26 deletions(-) diff --git a/README.md b/README.md index 283dc01..9b1a9b9 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,7 @@ A Gitlab bot for Matrix. It uses * [x] View commit diffs * [x] View commit history * [ ] Issue management - * [ ] Read issues + * [x] Read issues * [ ] Create/close/reopen issues * [ ] Read comments on issues * [ ] Comment on issues diff --git a/command-handler.go b/command-handler.go index eb03719..81bab32 100644 --- a/command-handler.go +++ b/command-handler.go @@ -22,22 +22,22 @@ import ( var permittedPreloginCommands = []string{"ping", "server", "login", "help"} -func handleCommand(room *mautrix.Room, sender, command string, args ...string) { +func handleCommand(room *mautrix.Room, sender, command string, args []string, lines []string) { git := getGitlabClient(sender) handler, ok := Commands[command] if !ok { - UnknownCommand(git, room, sender, command, args...) + UnknownCommand(git, room, sender, command, args) return } if git == nil { for _, cmd := range permittedPreloginCommands { if cmd == command { - handler(nil, room, sender, args...) + handler(nil, room, sender, args, lines) return } } - AuthOnlyCommand(room, sender, command, args...) + AuthOnlyCommand(room, sender, command, args) return } - handler(git, room, sender, args...) + handler(git, room, sender, args, lines) } diff --git a/commands.go b/commands.go index 0627a65..4d81359 100644 --- a/commands.go +++ b/commands.go @@ -28,17 +28,17 @@ import ( ) // UnknownCommand handles unknown !gitlab commands. -func UnknownCommand(git *gitlab.Client, room *mautrix.Room, sender, command string, args ...string) { +func UnknownCommand(git *gitlab.Client, room *mautrix.Room, sender, command string, args []string) { room.SendHTML("Unknown command. Type <code>!gitlab help</code> for help.") } // AuthOnlyCommand handles !gitlab commands that require authentication when the user hasn't logged in. -func AuthOnlyCommand(room *mautrix.Room, sender, command string, args ...string) { +func AuthOnlyCommand(room *mautrix.Room, sender, command string, args []string) { room.SendHTML("That command can only be used if you're logged in.\nTry <code>!gitlab login <access token></code>") } // GitlabCommand is a function that handles a !gitlab command. -type GitlabCommand func(git *gitlab.Client, room *mautrix.Room, sender string, args ...string) +type GitlabCommand func(git *gitlab.Client, room *mautrix.Room, sender string, args []string, lines []string) // Commands contains all the normal !gitlab commands. var Commands = map[string]GitlabCommand{ @@ -50,18 +50,19 @@ var Commands = map[string]GitlabCommand{ "diff": commandDiff, "log": commandLog, "whoami": commandWhoami, + "issue": commandIssue, "help": commandHelp, } -func commandPing(git *gitlab.Client, room *mautrix.Room, sender string, args ...string) { +func commandPing(git *gitlab.Client, room *mautrix.Room, sender string, args []string, lines []string) { room.Send("Pong.") } -func commandServer(git *gitlab.Client, room *mautrix.Room, sender string, args ...string) { +func commandServer(git *gitlab.Client, room *mautrix.Room, sender string, args []string, lines []string) { room.Sendf("I'm using the GitLab server at %s", config.GitLab.Domain) } -func commandLogin(git *gitlab.Client, room *mautrix.Room, sender string, args ...string) { +func commandLogin(git *gitlab.Client, room *mautrix.Room, sender string, args []string, lines []string) { if git != nil { room.Send("You're already logged in.") return @@ -72,14 +73,26 @@ func commandLogin(git *gitlab.Client, room *mautrix.Room, sender string, args .. room.Send(loginGitlab(sender, args[0])) } -func commandLogout(git *gitlab.Client, room *mautrix.Room, sender string, args ...string) { +func commandLogout(git *gitlab.Client, room *mautrix.Room, sender string, args []string, lines []string) { logoutGitlab(sender) room.Send("Access token removed successfully.") } -func commandHelp(git *gitlab.Client, room *mautrix.Room, sender string, args ...string) { +func commandHelp(git *gitlab.Client, room *mautrix.Room, sender string, args []string, lines []string) { if git != nil { - room.SendHTML(`<pre><code>Commands are prefixed with !gitlab + if len(args) > 0 { + if args[0] == "issue" { + room.SendHTML(`<pre><code>Commands are prefixed with !gitlab issue +- open <repo> <title> - Open an issue. The issue body can be placed on a new line. +- close <repo> <id> - Close an issue. +- comment <repo> <id> <message> - Comment on an issue. +- read <repo> <id> - Read an issue. +- read-comments <repo> <id> - Read comments on an issue. +</code></pre>`) + return + } + } + fmt.Println(room.SendHTML(`<pre><code>Commands are prefixed with !gitlab - ping - Ping the bot. - show <repo> <hash> - Get details about a specific commit. - diff <repo> <hash> - Get the diff of a specific commit. @@ -87,8 +100,9 @@ func commandHelp(git *gitlab.Client, room *mautrix.Room, sender string, args ... - whoami - Check who you're logged in as. - logout - Remove your GitLab access token from storage. - login <token> - Add a GitLab access token to storage. +- issue <...> - Manage issues. Type !gitlab help issue for details. - help - Show this help page. -</code></pre>`) +</code></pre>`)) } else { room.SendHTML(`<b>You're not logged in.</b><br/> <pre><code>Commands are prefixed with !gitlab @@ -100,7 +114,7 @@ func commandHelp(git *gitlab.Client, room *mautrix.Room, sender string, args ... } } -func commandWhoami(git *gitlab.Client, room *mautrix.Room, sender string, args ...string) { +func commandWhoami(git *gitlab.Client, room *mautrix.Room, sender string, args []string, lines []string) { user, _, err := git.Users.CurrentUser() if err != nil { room.Sendf("Unexpected error: %s", err) @@ -114,7 +128,7 @@ func commandWhoami(git *gitlab.Client, room *mautrix.Room, sender string, args . user.Name) } -func commandShow(git *gitlab.Client, room *mautrix.Room, sender string, args ...string) { +func commandShow(git *gitlab.Client, room *mautrix.Room, sender string, args []string, lines []string) { if len(args) < 2 { room.SendHTML("Usage: <code>!gitlab show <repo> <hash></code>") return @@ -136,7 +150,7 @@ func commandShow(git *gitlab.Client, room *mautrix.Room, sender string, args ... var diffLocationRegex = regexp.MustCompile("(@@ -[0-9]+,[0-9]+ \\+[0-9]+,[0-9]+ @@)") -func commandDiff(git *gitlab.Client, room *mautrix.Room, sender string, args ...string) { +func commandDiff(git *gitlab.Client, room *mautrix.Room, sender string, args []string, lines []string) { if len(args) < 2 { room.SendHTML("Usage: <code>!gitlab diff <repo> <hash></code>") return @@ -170,7 +184,7 @@ func commandDiff(git *gitlab.Client, room *mautrix.Room, sender string, args ... room.SendHTML(buf.String()) } -func commandLog(git *gitlab.Client, room *mautrix.Room, sender string, args ...string) { +func commandLog(git *gitlab.Client, room *mautrix.Room, sender string, args []string, lines []string) { if len(args) == 0 { room.SendHTML("Usage: <code>!gitlab log <repo> [n] [page]</code>") return @@ -204,3 +218,44 @@ func commandLog(git *gitlab.Client, room *mautrix.Room, sender string, args ...s room.SendHTML(buf.String()) } + +func commandIssue(git *gitlab.Client, room *mautrix.Room, sender string, args []string, lines []string) { + if len(args) == 0 { + room.SendHTML("Unknown subcommand. Try <code>!gitlab help issue</code> for help.") + return + } + + switch args[0] { + case "read": + if len(args) < 3 { + room.Send("Usage: !gitlab issue read <repo> <issue id>") + return + } + + id, err := strconv.Atoi(args[2]) + if err != nil { + room.Send("Usage: !gitlab issue read <repo> <issue id>") + return + } + + issue, _, err := git.Issues.GetIssue(args[1], id) + if err != nil { + room.Sendf("An error occurred: %s", err) + return + } + + var buf bytes.Buffer + fmt.Fprintf(&buf, "Issue #%[2]d by %[3]s: <a href='%[1]s'>%[4]s</a>.", issue.WebURL, issue.IID, issue.Author.Name, issue.Title) + if len(issue.Assignee.Name) > 0 { + fmt.Fprintf(&buf, " Assigned to %s.", issue.Assignee.Name) + } + fmt.Fprintf(&buf, "<br/>\n<blockquote>%s</blockquote><br/>\n", strings.Replace(issue.Description, "\n", "<br/>\n", -1)) + room.SendHTML(buf.String()) + case "open": + case "close": + case "comment": + case "read-comments": + default: + room.SendHTML("Unknown subcommand. Try <code>!gitlab help issue</code> for help.") + } +} diff --git a/config.go b/config.go index 4e29330..7de160f 100644 --- a/config.go +++ b/config.go @@ -30,10 +30,11 @@ type Config struct { } `json:"webhook"` Matrix struct { - Homeserver string `json:"homeserver"` - Username string `json:"username"` - Password string `json:"password"` - AuthToken string `json:"authtoken"` + Homeserver string `json:"homeserver"` + Username string `json:"username"` + Password string `json:"password"` + AuthToken string `json:"authtoken,omitempty"` + TransactionID int `json:"txnID,omitempty"` } GitLab struct { diff --git a/matrix.go b/matrix.go index bc259fb..f1a530a 100644 --- a/matrix.go +++ b/matrix.go @@ -37,6 +37,7 @@ func startMatrix() func() { saveConfig(*configPath) } else { mxbot.SetToken(config.Matrix.Username, config.Matrix.AuthToken) + mxbot.TxnID = config.Matrix.TransactionID } fmt.Println("Connected to Matrix homeserver at", config.Matrix.Homeserver, "as", config.Matrix.Username) @@ -59,13 +60,19 @@ func startMatrix() func() { continue Loop } msg = strings.TrimPrefix(msg, "!gitlab ") - parts := strings.Split(msg, " ") + lines := strings.Split(msg, "\n") + parts := strings.Split(lines[0], " ") + if len(lines) > 1 { + lines = lines[1:] + } else { + lines = []string{} + } cmd := parts[0] var args []string if len(parts) > 1 { args = parts[1:] } - handleCommand(evt.Room, evt.Sender, cmd, args...) + handleCommand(evt.Room, evt.Sender, cmd, args, lines) } case roomID := <-mxbot.InviteChan: invite := mxbot.Invites[roomID] @@ -78,5 +85,7 @@ func startMatrix() func() { return func() { stop <- true + config.Matrix.TransactionID = mxbot.TxnID + saveConfig(*configPath) } } -- GitLab