Skip to content
Snippets Groups Projects
Commit f1d6d530 authored by Tulir Asokan's avatar Tulir Asokan :cat2:
Browse files

Add issue reading and save transaction IDs between sessions

parent ec0928a9
No related branches found
No related tags found
No related merge requests found
...@@ -13,7 +13,7 @@ A Gitlab bot for Matrix. It uses ...@@ -13,7 +13,7 @@ A Gitlab bot for Matrix. It uses
* [x] View commit diffs * [x] View commit diffs
* [x] View commit history * [x] View commit history
* [ ] Issue management * [ ] Issue management
* [ ] Read issues * [x] Read issues
* [ ] Create/close/reopen issues * [ ] Create/close/reopen issues
* [ ] Read comments on issues * [ ] Read comments on issues
* [ ] Comment on issues * [ ] Comment on issues
......
...@@ -22,22 +22,22 @@ import ( ...@@ -22,22 +22,22 @@ import (
var permittedPreloginCommands = []string{"ping", "server", "login", "help"} 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) git := getGitlabClient(sender)
handler, ok := Commands[command] handler, ok := Commands[command]
if !ok { if !ok {
UnknownCommand(git, room, sender, command, args...) UnknownCommand(git, room, sender, command, args)
return return
} }
if git == nil { if git == nil {
for _, cmd := range permittedPreloginCommands { for _, cmd := range permittedPreloginCommands {
if cmd == command { if cmd == command {
handler(nil, room, sender, args...) handler(nil, room, sender, args, lines)
return return
} }
} }
AuthOnlyCommand(room, sender, command, args...) AuthOnlyCommand(room, sender, command, args)
return return
} }
handler(git, room, sender, args...) handler(git, room, sender, args, lines)
} }
...@@ -28,17 +28,17 @@ import ( ...@@ -28,17 +28,17 @@ import (
) )
// UnknownCommand handles unknown !gitlab commands. // 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.") 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. // 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 &lt;access token&gt;</code>") room.SendHTML("That command can only be used if you're logged in.\nTry <code>!gitlab login &lt;access token&gt;</code>")
} }
// GitlabCommand is a function that handles a !gitlab command. // 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. // Commands contains all the normal !gitlab commands.
var Commands = map[string]GitlabCommand{ var Commands = map[string]GitlabCommand{
...@@ -50,18 +50,19 @@ var Commands = map[string]GitlabCommand{ ...@@ -50,18 +50,19 @@ var Commands = map[string]GitlabCommand{
"diff": commandDiff, "diff": commandDiff,
"log": commandLog, "log": commandLog,
"whoami": commandWhoami, "whoami": commandWhoami,
"issue": commandIssue,
"help": commandHelp, "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.") 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) 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 { if git != nil {
room.Send("You're already logged in.") room.Send("You're already logged in.")
return return
...@@ -72,14 +73,26 @@ func commandLogin(git *gitlab.Client, room *mautrix.Room, sender string, args .. ...@@ -72,14 +73,26 @@ func commandLogin(git *gitlab.Client, room *mautrix.Room, sender string, args ..
room.Send(loginGitlab(sender, args[0])) 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) logoutGitlab(sender)
room.Send("Access token removed successfully.") 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 { 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 &lt;repo&gt; &lt;title&gt; - Open an issue. The issue body can be placed on a new line.
- close &lt;repo&gt; &lt;id&gt; - Close an issue.
- comment &lt;repo&gt; &lt;id&gt; &lt;message&gt; - Comment on an issue.
- read &lt;repo&gt; &lt;id&gt; - Read an issue.
- read-comments &lt;repo&gt; &lt;id&gt; - Read comments on an issue.
</code></pre>`)
return
}
}
fmt.Println(room.SendHTML(`<pre><code>Commands are prefixed with !gitlab
- ping - Ping the bot. - ping - Ping the bot.
- show &lt;repo&gt; &lt;hash&gt; - Get details about a specific commit. - show &lt;repo&gt; &lt;hash&gt; - Get details about a specific commit.
- diff &lt;repo&gt; &lt;hash&gt; - Get the diff of a specific commit. - diff &lt;repo&gt; &lt;hash&gt; - Get the diff of a specific commit.
...@@ -87,8 +100,9 @@ func commandHelp(git *gitlab.Client, room *mautrix.Room, sender string, args ... ...@@ -87,8 +100,9 @@ func commandHelp(git *gitlab.Client, room *mautrix.Room, sender string, args ...
- whoami - Check who you're logged in as. - whoami - Check who you're logged in as.
- logout - Remove your GitLab access token from storage. - logout - Remove your GitLab access token from storage.
- login &lt;token&gt; - Add a GitLab access token to storage. - login &lt;token&gt; - Add a GitLab access token to storage.
- issue &lt;...&gt; - Manage issues. Type !gitlab help issue for details.
- help - Show this help page. - help - Show this help page.
</code></pre>`) </code></pre>`))
} else { } else {
room.SendHTML(`<b>You're not logged in.</b><br/> room.SendHTML(`<b>You're not logged in.</b><br/>
<pre><code>Commands are prefixed with !gitlab <pre><code>Commands are prefixed with !gitlab
...@@ -100,7 +114,7 @@ func commandHelp(git *gitlab.Client, room *mautrix.Room, sender string, args ... ...@@ -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() user, _, err := git.Users.CurrentUser()
if err != nil { if err != nil {
room.Sendf("Unexpected error: %s", err) room.Sendf("Unexpected error: %s", err)
...@@ -114,7 +128,7 @@ func commandWhoami(git *gitlab.Client, room *mautrix.Room, sender string, args . ...@@ -114,7 +128,7 @@ func commandWhoami(git *gitlab.Client, room *mautrix.Room, sender string, args .
user.Name) 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 { if len(args) < 2 {
room.SendHTML("Usage: <code>!gitlab show &lt;repo&gt; &lt;hash&gt;</code>") room.SendHTML("Usage: <code>!gitlab show &lt;repo&gt; &lt;hash&gt;</code>")
return return
...@@ -136,7 +150,7 @@ func commandShow(git *gitlab.Client, room *mautrix.Room, sender string, args ... ...@@ -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]+ @@)") 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 { if len(args) < 2 {
room.SendHTML("Usage: <code>!gitlab diff &lt;repo&gt; &lt;hash&gt;</code>") room.SendHTML("Usage: <code>!gitlab diff &lt;repo&gt; &lt;hash&gt;</code>")
return return
...@@ -170,7 +184,7 @@ func commandDiff(git *gitlab.Client, room *mautrix.Room, sender string, args ... ...@@ -170,7 +184,7 @@ func commandDiff(git *gitlab.Client, room *mautrix.Room, sender string, args ...
room.SendHTML(buf.String()) 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 { if len(args) == 0 {
room.SendHTML("Usage: <code>!gitlab log &lt;repo&gt; [n] [page]</code>") room.SendHTML("Usage: <code>!gitlab log &lt;repo&gt; [n] [page]</code>")
return return
...@@ -204,3 +218,44 @@ func commandLog(git *gitlab.Client, room *mautrix.Room, sender string, args ...s ...@@ -204,3 +218,44 @@ func commandLog(git *gitlab.Client, room *mautrix.Room, sender string, args ...s
room.SendHTML(buf.String()) 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.")
}
}
...@@ -30,10 +30,11 @@ type Config struct { ...@@ -30,10 +30,11 @@ type Config struct {
} `json:"webhook"` } `json:"webhook"`
Matrix struct { Matrix struct {
Homeserver string `json:"homeserver"` Homeserver string `json:"homeserver"`
Username string `json:"username"` Username string `json:"username"`
Password string `json:"password"` Password string `json:"password"`
AuthToken string `json:"authtoken"` AuthToken string `json:"authtoken,omitempty"`
TransactionID int `json:"txnID,omitempty"`
} }
GitLab struct { GitLab struct {
......
...@@ -37,6 +37,7 @@ func startMatrix() func() { ...@@ -37,6 +37,7 @@ func startMatrix() func() {
saveConfig(*configPath) saveConfig(*configPath)
} else { } else {
mxbot.SetToken(config.Matrix.Username, config.Matrix.AuthToken) 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) fmt.Println("Connected to Matrix homeserver at", config.Matrix.Homeserver, "as", config.Matrix.Username)
...@@ -59,13 +60,19 @@ func startMatrix() func() { ...@@ -59,13 +60,19 @@ func startMatrix() func() {
continue Loop continue Loop
} }
msg = strings.TrimPrefix(msg, "!gitlab ") 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] cmd := parts[0]
var args []string var args []string
if len(parts) > 1 { if len(parts) > 1 {
args = parts[1:] args = parts[1:]
} }
handleCommand(evt.Room, evt.Sender, cmd, args...) handleCommand(evt.Room, evt.Sender, cmd, args, lines)
} }
case roomID := <-mxbot.InviteChan: case roomID := <-mxbot.InviteChan:
invite := mxbot.Invites[roomID] invite := mxbot.Invites[roomID]
...@@ -78,5 +85,7 @@ func startMatrix() func() { ...@@ -78,5 +85,7 @@ func startMatrix() func() {
return func() { return func() {
stop <- true stop <- true
config.Matrix.TransactionID = mxbot.TxnID
saveConfig(*configPath)
} }
} }
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment