John Olheiser
430500d9c9
All checks were successful
continuous-integration/drone/push Build is passing
Resolves #3 Co-authored-by: jolheiser <john.olheiser@gmail.com> Reviewed-on: #4
140 lines
3.0 KiB
Go
140 lines
3.0 KiB
Go
package command
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"regexp"
|
|
"strconv"
|
|
"strings"
|
|
|
|
"github.com/diamondburned/arikawa/v3/api"
|
|
"github.com/diamondburned/arikawa/v3/discord"
|
|
"github.com/diamondburned/arikawa/v3/utils/json/option"
|
|
"github.com/rs/zerolog/log"
|
|
)
|
|
|
|
func init() {
|
|
Commands["source"] = Source
|
|
}
|
|
|
|
// Source is the command for getting a forge.File by its path
|
|
var Source = Command{
|
|
Meta: api.CreateCommandData{
|
|
Name: "source",
|
|
Description: "File information",
|
|
Type: discord.ChatInputCommand,
|
|
Options: []discord.CommandOption{
|
|
&discord.StringOption{
|
|
OptionName: "path",
|
|
Description: "The path to the source file",
|
|
Required: true,
|
|
},
|
|
&discord.StringOption{
|
|
OptionName: "lines",
|
|
Description: "Specific lines in the source file",
|
|
},
|
|
&discord.StringOption{
|
|
OptionName: "branch",
|
|
Description: "Branch for the source file",
|
|
},
|
|
},
|
|
},
|
|
Handler: func(ctx *Context) {
|
|
if err := ctx.State.RespondInteraction(ctx.Event.ID, ctx.Event.Token, deferredInteraction); err != nil {
|
|
log.Err(err).Msg("")
|
|
return
|
|
}
|
|
|
|
var path, branch string
|
|
var lines *parsedLines
|
|
for _, opt := range ctx.Event.Data.(*discord.CommandInteraction).Options {
|
|
switch opt.Name {
|
|
case "path":
|
|
path = opt.String()
|
|
case "lines":
|
|
l, err := parseLines(opt.String())
|
|
if err != nil {
|
|
ctx.DeferredError(err.Error())
|
|
return
|
|
}
|
|
lines = l
|
|
case "branch":
|
|
branch = opt.String()
|
|
}
|
|
}
|
|
|
|
file, err := ctx.Forge.File(strings.TrimPrefix(path, "/"), branch)
|
|
if err != nil {
|
|
ctx.DeferredError("could not retrieve file")
|
|
return
|
|
}
|
|
|
|
content := fmt.Sprintf("<%s%s>", file.URL, lines.fragment())
|
|
if lines != nil {
|
|
contents := strings.Split(file.Contents, "\n")
|
|
content += fmt.Sprintf("\n```go\n%s\n```", strings.Join(contents[lines.lower():lines.upper()], "\n"))
|
|
}
|
|
if len(content) > 2000 {
|
|
content = content[:1991] + "//...\n```"
|
|
}
|
|
|
|
data := api.EditInteractionResponseData{
|
|
Content: option.NewNullableString(content),
|
|
}
|
|
|
|
if _, err := ctx.State.EditInteractionResponse(ctx.App.ID, ctx.Event.Token, data); err != nil {
|
|
log.Err(err).Msg("")
|
|
}
|
|
},
|
|
}
|
|
|
|
// https://regex101.com/r/uxrKKs/2
|
|
var linesRe = regexp.MustCompile(`^[Ll]?(\d+)(?:-[Ll]?(\d+))?$`)
|
|
|
|
type parsedLines struct {
|
|
from int
|
|
to int
|
|
}
|
|
|
|
func (l *parsedLines) fragment() string {
|
|
if l == nil {
|
|
return ""
|
|
}
|
|
str := fmt.Sprintf("#L%d", l.from)
|
|
if l.to > 0 {
|
|
str += fmt.Sprintf("-L%d", l.to)
|
|
}
|
|
return str
|
|
}
|
|
|
|
func (l *parsedLines) lower() int {
|
|
return l.from - 1
|
|
}
|
|
|
|
func (l *parsedLines) upper() int {
|
|
if l.to != 0 {
|
|
return l.to
|
|
}
|
|
return l.from
|
|
}
|
|
|
|
func parseLines(in string) (*parsedLines, error) {
|
|
match := linesRe.FindStringSubmatch(in)
|
|
if match[1] == "" {
|
|
return nil, errors.New("improper lines given; example L1-L5")
|
|
}
|
|
from, err := strconv.Atoi(match[1])
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
l := &parsedLines{from: from}
|
|
if match[2] != "" {
|
|
to, err := strconv.Atoi(match[2])
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
l.to = to
|
|
}
|
|
return l, nil
|
|
}
|