diff --git a/pages/commit.go b/pages/commit.go new file mode 100644 index 0000000..c270d8f --- /dev/null +++ b/pages/commit.go @@ -0,0 +1,123 @@ +package pages + +import ( + "bufio" + "bytes" + "context" + htmlfmt "github.com/alecthomas/chroma/v2/formatters/html" + "github.com/alecthomas/chroma/v2/lexers" + "github.com/alecthomas/chroma/v2/styles" + "github.com/carlmjohnson/requests" + "github.com/gocolly/colly" + "github.com/gofiber/fiber/v2" + "html/template" + "log" + "net/http" + "os" + "regexp" + "strings" +) + +type Commit struct { + CommitName string + CommitDesc string + CommitHashShortened string + CommitDate string + Commiter []string + CommitToBranch string + PreviousCommit string + Additions int64 + Deletions int64 + ChangedFiles int64 + FullName string +} + +func HandleCommit(c *fiber.Ctx) error { + var commitArray []Commit + + resp, statusErr := http.Get("https://github.com/" + c.Params("user") + "/" + c.Params("repo") + "/commit/" + c.Params("commit") + "/") + if statusErr != nil { + log.Println(statusErr) + } + if resp.StatusCode == 404 { + // I need a better way to do this + return c.Status(404).Render("error", fiber.Map{ + "title": "Error", + "error": "Commit" + c.Params("commit") + "not found", + }) + } + var file string + url := "https://github.com/" + c.Params("user") + "/" + c.Params("repo") + "/commit/" + c.Params("commit") + ".patch" + err := requests. + URL(url). + ToString(&file). + Fetch(context.Background()) + if err != nil { + return c.Status(404).Render("error", fiber.Map{ + "error": err, + }) + } + re := regexp.MustCompile("\\A(?s).*?---(?-s).*\\n") + file = re.ReplaceAllString(file, "---\n") + lexer := lexers.Match("something.diff") + if lexer == nil { + lexer = lexers.Fallback + } + formatter := htmlfmt.New( + htmlfmt.WithClasses(true), + htmlfmt.WithLineNumbers(true), + htmlfmt.PreventSurroundingPre(false), + ) + + buf := bytes.Buffer{} + writer := bufio.NewWriter(&buf) + style := styles.Get("native") + tokens, err := lexer.Tokenise(nil, file) + if err != nil { + return c.Status(500).Render("error", fiber.Map{ + "error": err, + }) + } + formatter.Format(writer, style, tokens) + + cssbuf := bytes.Buffer{} + cssw := bufio.NewWriter(&cssbuf) + formatter.WriteCSS(cssw, style) + writer.Flush() + cssw.Flush() + + // Scraping + Scrape := Commit{} + UserAgent, ok := os.LookupEnv("GOTHUB_USER_AGENT") + if !ok { + UserAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/110.0.0.0 Safari/537.36" + } + + sc := colly.NewCollector(colly.AllowedDomains("github.com"), colly.UserAgent(UserAgent)) + sc.OnHTML("div.commit", func(e *colly.HTMLElement) { + Scrape.CommitName = e.ChildText("div.commit-title") + Scrape.CommitDesc = e.ChildText("div.commit-desc pre") + Scrape.CommitHashShortened = e.ChildText("div.text-lg-right span.m-0 span.sha") + Scrape.PreviousCommit = e.ChildText("div.text-lg-right span.ml-0 a.sha") + Scrape.CommitDate = e.ChildText("div.flex-self-start relative-time") + Scrape.CommitToBranch = e.ChildText("ul.branches-list li.branch a") + e.ForEach("div.flex-self-start .commit-author", func(i int, el *colly.HTMLElement) { + Scrape.Commiter = append(Scrape.Commiter, strings.TrimPrefix(el.Attr("title"), "View all commits by ")) + }) + }) + Scrape.FullName = c.Params("user") + "/" + c.Params("repo") + sc.Visit("https://github.com/" + c.Params("user") + "/" + c.Params("repo") + "/commit/" + c.Params("commit") + "/") + if len(Scrape.PreviousCommit) > 7 { + Minus := len(Scrape.PreviousCommit) - 7 + Scrape.PreviousCommit = Scrape.PreviousCommit[:len(Scrape.PreviousCommit)-Minus] + } + // Add scrape-based info to commitArray + commitArray = append(commitArray, Scrape) + + return c.Render("commit", fiber.Map{ + "title": "Commit " + Scrape.CommitName + " | " + c.Params("user") + "/" + c.Params("repo"), + "commit": commitArray, + "file": template.HTML(buf.String()), + "css": template.CSS(cssbuf.String()), + }) +} diff --git a/serve/serve.go b/serve/serve.go index 655c7db..af7eea7 100644 --- a/serve/serve.go +++ b/serve/serve.go @@ -139,6 +139,7 @@ func Serve(port string) { } }) app.Get("/:user/:repo", pages.HandleRepo) + app.Get("/:user/:repo/commit/:commit", pages.HandleCommit) app.Get("/:user/:repo/info/+", func(c *fiber.Ctx) error { // This is needed but it looks like git doesn't send it. Or maybe i just shouldn't program at midnight param := "?service=git-upload-pack" diff --git a/views/commit.html b/views/commit.html new file mode 100644 index 0000000..9b88fbe --- /dev/null +++ b/views/commit.html @@ -0,0 +1,46 @@ +{{ template "header" .}} + +
+ {{ if.commit }} + + {{ range $key, $value := .commit}} +
+ Back to {{.FullName}} +
+ +
+
+

{{.CommitHashShortened}} | {{.CommitName}}

+ Raw +
+ {{.CommitName}} {{ if .CommitDesc }} +
{{.CommitDesc}}
+ {{end}} +

+ Commited on {{.CommitDate}} by {{range .Commiter}} + @{{.}}{{ end }} +

+

+ Previous Commit: + {{.PreviousCommit}} +

+
+ {{end}} {{ .file}} {{ else }} +

Commit not found

+

That commit doesn't exist.

+ {{ end }} +
+{{ template "footer" .}}