AuraGem Servers > Tree [main]

/gemini/github.go/

..
View Raw
package gemini

import (
	"context"
	"fmt"
	"mime"
	"path"
	"strconv"
	"strings"

	// "net/url"

	"github.com/google/go-github/v60/github"
	"gitlab.com/clseibold/auragem_sis/config"
	sis "gitlab.com/sis-suite/smallnetinformationservices"
	"golang.org/x/oauth2"
)

var apiToken = config.GithubToken

func handleGithub(g sis.VirtualServerHandle) {
	ctx := context.Background()
	ts := oauth2.StaticTokenSource(
		&oauth2.Token{AccessToken: apiToken},
	)
	tc := oauth2.NewClient(ctx, ts)
	client := github.NewClient(tc)

	g.AddRoute("/github", func(request *sis.Request) {
		request.SetClassification(sis.ScrollResponseUDC_Reference)
		request.Gemini(`# AuraGem Github Proxy

Welcome to the AuraGem Github proxy!

=> /github/search Search Repos

`)

}) g.AddRoute("/github/search/:page", func(request *sis.Request) { //query, err2 := c.QueryString() query, err := request.Query() if err != nil { request.TemporaryFailure(err.Error()) return } else if query == "" { request.RequestInput("Search Query:") //return c.NoContent(gig.StatusInput, "Search Query:") } else { handleGithubSearch(ctx, request, client, query, request.GetParam("page")) } }) g.AddRoute("/github/search", func(request *sis.Request) { //query, err2 := c.QueryString() query, err := request.Query() if err != nil { request.TemporaryFailure(err.Error()) return } else if query == "" { request.RequestInput("Search Query:") //return c.NoContent(gig.StatusInput, "Search Query:") } else { handleGithubSearch(ctx, request, client, query, "") } }) g.AddRoute("/github/repo/:id", func(request *sis.Request) { request.SetClassification(sis.ScrollResponseUDC_Docs) id := request.GetParam("id") template := `# Repo: %s %s SSH Url: %s HTML Url: %s Homepage: %s => %s License: %s => /github/repo/%d/issues/ Issues => /github/repo/%d/b Branches ## Contents - Branch %s %s

`

id_int, err1 := strconv.Atoi(id) if err1 != nil { panic(err1) } repository, _, err2 := client.Repositories.GetByID(ctx, int64(id_int)) if err2 != nil { panic(err2) } // TODO: README, README.md, readme.md /*opts := &github.RepositoryContentGetOptions{} readmeContents, _, _, err3 := client.Repositories.GetContents(ctx, repository.GetOwner().GetLogin(), repository.GetName(), "README.md", opts) readmeContents_str := "" var err4 error if err3 != nil { readmeContents, _, _, err3 = client.Repositories.GetContents(ctx, *repository.GetOwner().Login, repository.GetName(), "readme.md", opts) if err3 == nil { readmeContents_str, err4 = readmeContents.GetContent() } } else { readmeContents_str, err4 = readmeContents.GetContent() } if err4 != nil { panic(err4) }*/ rootContents, _ := getRepoContents(ctx, client, repository, "") request.Gemini(fmt.Sprintf(template, repository.GetFullName(), repository.GetDescription(), repository.GetSSHURL(), repository.GetHTMLURL(), repository.GetHomepage(), repository.GetLicense().GetURL(), repository.GetLicense().GetName(), repository.GetID(), repository.GetID(), repository.GetDefaultBranch(), rootContents)) }) g.AddRoute("/github/repo/:id/b", func(request *sis.Request) { request.SetClassification(sis.ScrollResponseUDC_Docs) id := request.GetParam("id") id_int, err1 := strconv.Atoi(id) if err1 != nil { panic(err1) } repository, _, err2 := client.Repositories.GetByID(ctx, int64(id_int)) if err2 != nil { panic(err2) } template := `# Repo: %s - Branches => /github/repo/%d Repo Home %s` opts2 := &github.BranchListOptions{} branches, _, err3 := client.Repositories.ListBranches(ctx, repository.GetOwner().GetLogin(), repository.GetName(), opts2) if err3 != nil { panic(err3) } var builder strings.Builder for _, branch := range branches { fmt.Fprintf(&builder, "=> /github/repo/%d/b/%s %s\n", repository.GetID(), branch.GetName(), branch.GetName()) } request.Gemini(fmt.Sprintf(template, repository.GetFullName(), repository.GetID(), builder.String())) }) g.AddRoute("/github/repo/:id/issues/", func(request *sis.Request) { request.SetClassification(sis.ScrollResponseUDC_Docs) id := request.GetParam("id") id_int, err1 := strconv.Atoi(id) if err1 != nil { panic(err1) } repository, _, err2 := client.Repositories.GetByID(ctx, int64(id_int)) if err2 != nil { panic(err2) } //client.Repositories.ListCommits() //client.Repositories.ListReleases() // Opts for filtering: Milestone (number, none, *), State (open, closed, all), Sort (updated, created, comments) opts := &github.IssueListByRepoOptions{State: "open", Sort: "updated", Direction: "desc"} opts.PerPage = 100 issues, _, err := client.Issues.ListByRepo(ctx, repository.GetOwner().GetLogin(), repository.GetName(), opts) if err != nil { panic(err) // TODO } var builder strings.Builder for _, issue := range issues { fmt.Fprintf(&builder, "=> /github/repo/%d/issues/%d %s #%d: %s (%s)\n", repository.GetID(), issue.GetNumber(), issue.GetCreatedAt().Format("2006-01-02"), issue.GetNumber(), issue.GetTitle(), issue.User.GetLogin()) } request.Gemini(fmt.Sprintf(`# %s Open Issues (%d) => /github/repo/%d Repo Home %s

`, repository.GetFullName(), len(issues), repository.GetID(), builder.String()))

}) g.AddRoute("/github/repo/:id/issues/:issue", func(request *sis.Request) { request.SetClassification(sis.ScrollResponseUDC_Docs) id := request.GetParam("id") issueParam := request.GetParam("issue") id_int, err1 := strconv.Atoi(id) if err1 != nil { panic(err1) } issue_int, err2 := strconv.Atoi(issueParam) if err2 != nil { panic(err2) } repository, _, err2 := client.Repositories.GetByID(ctx, int64(id_int)) if err2 != nil { panic(err2) } issue, _, err := client.Issues.Get(ctx, repository.GetOwner().GetLogin(), repository.GetName(), issue_int) if err != nil { panic(err) // TODO } // Get Comments on the Issue sort := "created" direction := "asc" opts := &github.IssueListCommentsOptions{Sort: &sort, Direction: &direction} comments, _, err3 := client.Issues.ListComments(ctx, repository.GetOwner().GetLogin(), repository.GetName(), issue.GetNumber(), opts) if err3 != nil { panic(err3) } var builder strings.Builder for _, comment := range comments { fmt.Fprintf(&builder, "### %s %s\n\n%s\n\n", comment.GetCreatedAt().Format("2006-01-02 15:04:05"), comment.GetUser().GetLogin(), comment.GetBody()) } request.Gemini(fmt.Sprintf(`# %s Issue #%d: %s => /github/repo/%d Repo Home => /github/repo/%d/issues/ Issues ## %s %s %s ## Comments (%d) %s

`, repository.GetFullName(), issue.GetNumber(), issue.GetTitle(), repository.GetID(), repository.GetID(), issue.GetCreatedAt().Format("2006-01-02 15:04:05"), issue.GetUser().GetLogin(), issue.GetBody(), len(comments), builder.String()))

}) g.AddRoute("/github/repo/:id/files/*", func(request *sis.Request) { id := request.GetParam("id") route := fmt.Sprintf("/github/repo/%s/files", id) p := strings.Replace(request.RawPath(), route, "", 1) id_int, err1 := strconv.Atoi(id) if err1 != nil { panic(err1) } repository, _, err2 := client.Repositories.GetByID(ctx, int64(id_int)) if err2 != nil { panic(err2) } template := `# Repo Contents: %s - Branch %s Path: %s .. %s

`

contents, isFile := getRepoContents(ctx, client, repository, p) if isFile { if strings.HasSuffix(p, ".gmi") || strings.HasSuffix(p, ".gemini") { request.Gemini(contents) } else if strings.HasSuffix(p, ".md") { request.TextWithMimetype("text/markdown", contents) } else if strings.HasSuffix(p, ".rss") || strings.HasSuffix(p, ".atom") { request.Bytes("text/rss", []byte(contents)) } else if strings.HasSuffix(p, ".gpub") { request.Bytes("application/gpub+zip", []byte(contents)) } else { extension := path.Ext(p) mimeType := mime.TypeByExtension(extension) if mimeType == "" { //return c.Text(contents) request.TextWithMimetype("text/plain", contents) } else { request.TextWithMimetype(mimeType, contents) } } } else { request.Gemini(fmt.Sprintf(template, repository.GetFullName(), repository.GetDefaultBranch(), p, contents)) } }) } func getRepoContents(ctx context.Context, client *github.Client, repository *github.Repository, path string) (string, bool) { opts := &github.RepositoryContentGetOptions{} fileContents, dirContents, _, err := client.Repositories.GetContents(ctx, repository.GetOwner().GetLogin(), repository.GetName(), path, opts) if err != nil { //panic(err) // TODO return "Not found.", false } var builder strings.Builder if dirContents != nil { for _, v := range dirContents { // TODO: Use PathEscape for each part of the path, but cannot escape the whole path (otherwise "/" will turn into "%2F") // OR, switch this to use a query string so that I can use QueryEscape? fmt.Fprintf(&builder, "=> /github/repo/%d/files/%s %s\n", repository.GetID(), v.GetPath(), v.GetName()) } return builder.String(), false } if fileContents != nil { c, _ := fileContents.GetContent() return c, true } fmt.Fprintf(&builder, "Not found") return builder.String(), false } func handleGithubSearch(ctx context.Context, request *sis.Request, client *github.Client, query string, page string) { template := `# Github Search => /github/search New Search %s` opts := &github.SearchOptions{} result, _, err := client.Search.Repositories(ctx, query, opts) if err != nil { panic(err) } var builder strings.Builder for _, repository := range result.Repositories { fmt.Fprintf(&builder, "=> /github/repo/%d %s\n%s\n\n", repository.GetID(), repository.GetFullName(), repository.GetDescription()) } request.Gemini(fmt.Sprintf(template, builder.String())) }