2022-12-27 22:31:07 -05:00
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
"html/template"
|
|
|
|
"strings"
|
|
|
|
|
|
|
|
"github.com/PuerkitoBio/goquery"
|
|
|
|
"github.com/gin-gonic/gin"
|
|
|
|
|
|
|
|
"github.com/go-resty/resty/v2"
|
|
|
|
)
|
|
|
|
|
|
|
|
func main() {
|
|
|
|
|
|
|
|
client := resty.New()
|
|
|
|
|
|
|
|
r := gin.Default()
|
|
|
|
|
|
|
|
r.LoadHTMLGlob("templates/*")
|
|
|
|
r.Static("/static", "./public")
|
|
|
|
|
|
|
|
r.GET("/questions/:id/:title", func(c *gin.Context) {
|
|
|
|
questionId := c.Param("id")
|
|
|
|
questionTitle := c.Param("title")
|
|
|
|
|
|
|
|
soLink := fmt.Sprintf("https://stackoverflow.com/questions/%s/%s", questionId, questionTitle)
|
|
|
|
|
|
|
|
resp, err := client.R().Get(soLink)
|
|
|
|
if err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
respBody := resp.String()
|
|
|
|
|
|
|
|
respBodyReader := strings.NewReader(respBody)
|
|
|
|
|
|
|
|
doc, err := goquery.NewDocumentFromReader(respBodyReader)
|
|
|
|
if err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
questionTextParent := doc.Find("h1.fs-headline1")
|
|
|
|
|
|
|
|
questionText := questionTextParent.Children().First().Text()
|
|
|
|
|
|
|
|
questionBodyParent := doc.Find("div.s-prose")
|
|
|
|
|
|
|
|
questionBodyParentHTML, err := questionBodyParent.Html()
|
|
|
|
if err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
|
2022-12-27 22:46:31 -05:00
|
|
|
questionCard := doc.Find("div.postcell")
|
|
|
|
|
|
|
|
questionMetadata := questionCard.Find("div.user-info")
|
|
|
|
questionTimestamp := ""
|
|
|
|
questionMetadata.Find("span.relativetime").Each(func(i int, s *goquery.Selection) {
|
|
|
|
// get the second
|
|
|
|
if i == 0 {
|
|
|
|
if s.Text() != "" {
|
|
|
|
// if it's not been edited, it means it's the first
|
|
|
|
questionTimestamp = s.Text()
|
|
|
|
return
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// otherwise it's the second element
|
|
|
|
if i == 1 {
|
|
|
|
questionTimestamp = s.Text()
|
|
|
|
return
|
|
|
|
}
|
|
|
|
})
|
|
|
|
|
|
|
|
userDetails := questionMetadata.Find("div.user-details")
|
|
|
|
|
|
|
|
questionAuthor := ""
|
|
|
|
questionAuthorURL := ""
|
|
|
|
|
|
|
|
userDetails.Find("a").Each(func(i int, s *goquery.Selection) {
|
|
|
|
// get the second
|
|
|
|
if i == 0 {
|
|
|
|
if s.Text() != "" {
|
|
|
|
// if it's not been edited, it means it's the first
|
|
|
|
questionAuthor = s.Text()
|
|
|
|
questionAuthorURL, _ = s.Attr("href")
|
|
|
|
return
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// otherwise it's the second element
|
|
|
|
if i == 1 {
|
|
|
|
questionAuthor = s.Text()
|
|
|
|
questionAuthorURL, _ = s.Attr("href")
|
|
|
|
return
|
|
|
|
}
|
|
|
|
})
|
|
|
|
|
2022-12-27 22:50:38 -05:00
|
|
|
answers := []template.HTML{}
|
|
|
|
doc.Find("div.answer").Each(func(i int, s *goquery.Selection) {
|
|
|
|
postLayout := s.Find("div.post-layout")
|
|
|
|
answerCell := postLayout.Find("div.answercell")
|
|
|
|
answerBody := answerCell.Find("div.s-prose")
|
|
|
|
answerBodyHTML, _ := answerBody.Html()
|
|
|
|
answers = append(answers, template.HTML(answerBodyHTML))
|
|
|
|
})
|
|
|
|
|
2022-12-27 22:31:07 -05:00
|
|
|
c.HTML(200, "question.html", gin.H{
|
2022-12-27 22:46:31 -05:00
|
|
|
"title": questionText,
|
|
|
|
"body": template.HTML(questionBodyParentHTML),
|
|
|
|
"timestamp": questionTimestamp,
|
|
|
|
"author": questionAuthor,
|
|
|
|
"authorURL": questionAuthorURL,
|
2022-12-27 22:50:38 -05:00
|
|
|
"answers": answers,
|
2022-12-27 22:31:07 -05:00
|
|
|
})
|
|
|
|
|
|
|
|
})
|
|
|
|
r.Run("localhost:8080")
|
|
|
|
}
|