package pages import ( "log" "net/http" "net/url" "os" "strings" "time" "gitler.moe/suwako/gitlin/utils" "github.com/gocolly/colly" "github.com/gofiber/fiber/v2" ) type ( Commits struct { Date, Next, Prev string Commit []Commit } Commit struct { Mess, User, Id, IdShort, Issue, Ava string } ) func HandleCommits (c *fiber.Ctx) error { var commitsArray []Commits branch := "" if strings.Count(c.Params("branch"), "")-1 > 0 { branch = c.Params("branch") } repoUrl := strings.TrimSuffix(c.Params("repo"), ".git") endurl := "" if branch != "" { endurl = "/" + branch if c.Query("after") != "" { endurl += "?after=" + url.QueryEscape(c.Query("after")) + "&branch=" + url.QueryEscape(c.Query("branch")) + "&qualified_name=" + url.QueryEscape(c.Query("qualified_name")) } else if c.Query("before") != "" { endurl += "?before=" + url.QueryEscape(c.Query("before")) + "&branch=" + url.QueryEscape(c.Query("branch")) + "&qualified_name=" + url.QueryEscape(c.Query("qualified_name")) } } else if (c.Query("author") != "") { if c.Query("after") != "" { endurl = "?after=" + url.QueryEscape(c.Query("after")) + "&author=" + url.QueryEscape(c.Query("author")) } else if c.Query("before") != "" { endurl = "?before=" + url.QueryEscape(c.Query("before")) + "&author=" + url.QueryEscape(c.Query("author")) } else { endurl = "?author=" + url.QueryEscape(c.Query("author")) } } resp, err := http.Get("https://github.com/" + c.Params("user") + "/" + repoUrl + "/commits" + endurl) if err != nil { log.Println(err) } if resp.StatusCode == 404 { return c.Status(404).Render("error", fiber.Map { "title": "Error", "ver": utils.Ver, "ves": utils.Ves, "error": "Repository " + c.Params("user") + "/" + repoUrl + "/commits" + endurl + " not found", }) } Scrape := Commits{} ua, ok := os.LookupEnv("GITLIN_USER_AGENT") if !ok { ua = "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(ua)) sc.Limit(&colly.LimitRule { DomainGlob: "github.githubassets.com/*", Delay: 30 * time.Second, RandomDelay: 30 * time.Second, }) sc.OnRequest(func(r *colly.Request) { r.Headers.Set("Cache-Control", "no-cache, no-store, must-revalidate") r.Headers.Set("Pragma", "no-cache") r.Headers.Set("Expires", "0") }) sc.OnHTML("div.repository-content div.container-xl div.js-navigation-container", func (e *colly.HTMLElement) { e.ForEach("div.TimelineItem div.TimelineItem-body", func (i int, el *colly.HTMLElement) { tdate := strings.TrimPrefix(el.ChildText("h2.f5"), "Commits on ") td, e := time.Parse("Jan 2, 2006", tdate) if e != nil { log.Println(e) } Scrape.Date = td.Format("2006年01月02日") el.ForEach("ol.Box", func (ij int, eli *colly.HTMLElement) { var mess, id, issue, idshort, user, ava string var commitArray []Commit eli.ForEach("li.Box-row", func (ijk int, elin *colly.HTMLElement) { mess, id, issue, idshort, user, ava = "", "", "", "", "", "" mess += elin.ChildText("div.Details p.mb-1 a") issue = strings.ReplaceAll(elin.ChildAttr("div.Details p.mb-1 a.issue-link", "href"), "https://github.com/" + c.Params("user") + "/" + repoUrl + "/pull/", "") id = strings.TrimPrefix(elin.ChildAttr("div.Details p.mb-1 a", "href"), "/" + c.Params("user") + "/" + repoUrl + "/commit/") idshort = id[:7] eli.ForEach("div.Details div.mt-1 div.f6", func (iju int, eliu *colly.HTMLElement) { user = eliu.ChildText("a") }) eli.ForEach("div.Details div.d-flex div.AvatarStack div.AvatarStack-body a.avatar", func (ijh int, elia *colly.HTMLElement) { ava = elia.ChildAttr("img", "src") if (strings.Contains(ava, "https://avatars.githubusercontent.com/in")) { ava = strings.ReplaceAll(ava, "https://avatars.githubusercontent.com/in", "/avatar") } else { ava = strings.ReplaceAll(ava, "https://avatars.githubusercontent.com/u", "/avatar") } }) commitArray = append(commitArray, Commit{ Mess: mess, User: user, Id: id, IdShort: idshort, Issue: issue, Ava: ava, }) }) Scrape.Commit = commitArray }) commitsArray = append(commitsArray, Scrape) }) }) sc.OnHTML(`div.repository-content div.container-xl div.paginate-container div.BtnGroup a:contains("Newer")`, func(e *colly.HTMLElement) { Scrape.Next = strings.TrimPrefix(e.Attr("href"), "https://github.com") }) sc.OnHTML(`div.repository-content div.container-xl div.paginate-container div.BtnGroup a:contains("Older")`, func(e *colly.HTMLElement) { Scrape.Prev = strings.TrimPrefix(e.Attr("href"), "https://github.com") }) sc.Visit("https://github.com/" + c.Params("user") + "/" + repoUrl + "/commits" + endurl) return c.Render("commits", fiber.Map{ "title": c.Params("user") + "/" + repoUrl + "/commits" + endurl, "username": c.Params("user"), "reponame": repoUrl, "branch": branch, "author": c.Query("author"), "ver": utils.Ver, "ves": utils.Ves, "prev": Scrape.Prev, "next": Scrape.Next, "commits": commitsArray, }) }