Compare commits

...

8 Commits

Author SHA1 Message Date
httpjamesm 487a62e7aa chore: version 1.8 2023-02-20 14:23:42 -05:00
httpjamesm abfd0cfb6f feat: SO/SE converter
refactor: rework some author logic
2023-02-20 14:17:24 -05:00
httpjamesm 63a30ab1cf feat: don't count static toward ratelimit 2023-02-20 13:56:44 -05:00
httpjamesm f1370c29b6 fix: pass down domain to comment for author URLs 2023-02-20 13:54:09 -05:00
httpjamesm d935ce72f6 fix: pass domain to question template 2023-02-20 13:49:54 -05:00
httpjamesm 45644a0503 feat: get stackexchange posts
fix: comment author distinguishing
2023-02-16 10:25:24 -05:00
httpjamesm f81b726612 chore: version 1.7.1 2023-02-14 20:25:26 -05:00
httpjamesm c55b8b6ed5 fix: redeclare correct answer author vars 2023-02-14 20:25:16 -05:00
8 changed files with 80 additions and 33 deletions
+1 -1
View File
@@ -1,3 +1,3 @@
package config
var Version = "1.7"
var Version = "1.8"
+9
View File
@@ -59,6 +59,15 @@ func main() {
// redirect user to the answer with the title
c.Redirect(302, fmt.Sprintf("/questions/%s/%s#%s", c.Param("id"), c.Param("title"), c.Param("answerId")))
})
r.GET("/exchange/:sub/questions/:id/:title", routes.ViewQuestion)
r.GET("/exchange/:sub/questions/:id", func(c *gin.Context) {
// redirect user to the question with the title
c.Redirect(302, fmt.Sprintf("/exchange/%s/questions/%s/placeholder", c.Param("sub"), c.Param("id")))
})
r.GET("/exchange/:sub/questions/:id/:title/:answerId", func(c *gin.Context) {
// redirect user to the answer with the title
c.Redirect(302, fmt.Sprintf("/exchange/%s/questions/%s/%s#%s", c.Param("sub"), c.Param("id"), c.Param("title"), c.Param("answerId")))
})
r.GET("/proxy", routes.GetImage)
+7
View File
@@ -2,6 +2,7 @@ package middleware
import (
"anonymousoverflow/config"
"strings"
"sync"
"time"
@@ -12,6 +13,12 @@ var ipMap = sync.Map{}
func Ratelimit() gin.HandlerFunc {
return func(c *gin.Context) {
if strings.HasPrefix(c.Request.URL.Path, "/static") {
c.Next()
return
}
ip := c.ClientIP()
// log request count as the value, ip as key
+16 -4
View File
@@ -3,6 +3,7 @@ package routes
import (
"anonymousoverflow/config"
"fmt"
"regexp"
"strings"
"github.com/gin-gonic/gin"
@@ -19,6 +20,8 @@ type urlConversionRequest struct {
URL string `form:"url" binding:"required"`
}
var stackExchangeRegex = regexp.MustCompile(`https://(.+).stackexchange.com/questions/`)
func PostHome(c *gin.Context) {
body := urlConversionRequest{}
@@ -33,15 +36,24 @@ func PostHome(c *gin.Context) {
soLink := body.URL
// validate URL
if !strings.HasPrefix(soLink, "https://stackoverflow.com/questions/") {
isStackOverflow := strings.HasPrefix(soLink, "https://stackoverflow.com/questions/")
isStackExchange := stackExchangeRegex.MatchString(soLink)
if !isStackExchange && !isStackOverflow {
c.HTML(400, "home.html", gin.H{
"errorMessage": "Invalid stack overflow URL",
"errorMessage": "Invalid stack overflow/exchange URL",
"theme": c.MustGet("theme").(string),
})
return
}
// redirect to the proxied thread
c.Redirect(302, fmt.Sprintf("/questions/%s", strings.TrimPrefix(soLink, "https://stackoverflow.com/questions/")))
// if stack overflow, trim https://stackoverflow.com
if isStackOverflow {
c.Redirect(302, strings.TrimPrefix(soLink, "https://stackoverflow.com"))
return
}
// if stack exchange, extract the subdomain
sub := stackExchangeRegex.FindStringSubmatch(soLink)[1]
c.Redirect(302, fmt.Sprintf("/exchange/%s/%s", sub, strings.TrimPrefix(soLink, fmt.Sprintf("https://%s.stackexchange.com", sub))))
}
+40 -22
View File
@@ -53,7 +53,15 @@ func ViewQuestion(c *gin.Context) {
soSortValue = soSortValues["votes"]
}
soLink := fmt.Sprintf("https://stackoverflow.com/questions/%s/%s?answertab=%s", questionId, questionTitle, soSortValue)
sub := c.Param("sub")
domain := "stackoverflow.com"
if sub != "" {
domain = fmt.Sprintf("%s.stackexchange.com", sub)
}
soLink := fmt.Sprintf("https://%s/questions/%s/%s?answertab=%s", domain, questionId, questionTitle, soSortValue)
resp, err := client.R().Get(soLink)
if err != nil {
@@ -129,7 +137,7 @@ func ViewQuestion(c *gin.Context) {
newFilteredQuestion.ShortenedBody = shortenedBody
comments := utils.FindAndReturnComments(questionBodyParentHTML, questionPostLayout)
comments := utils.FindAndReturnComments(questionBodyParentHTML, domain, questionPostLayout)
newFilteredQuestion.Comments = comments
// parse any code blocks and highlight them
@@ -170,24 +178,33 @@ func ViewQuestion(c *gin.Context) {
userDetails := questionMetadata.Find("div.user-details")
questionAuthor := ""
questionAuthorURL := ""
questionAuthorURL := fmt.Sprintf("https://%s", domain)
// check if the question has been edited
isQuestionEdited := false
questionMetadata.Find("a.js-gps-track").Each(func(i int, s *goquery.Selection) {
if strings.Contains(s.Text(), "edited") {
isQuestionEdited = true
return
}
})
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
// if question has been edited, the author is the second element.
if isQuestionEdited {
if i == 1 {
questionAuthor = s.Text()
questionAuthorURL, _ = s.Attr("href")
questionAuthorURL += s.AttrOr("href", "")
return
}
} else {
// otherwise it's the first element
if i == 0 {
questionAuthor = s.Text()
questionAuthorURL += s.AttrOr("href", "")
return
}
}
// otherwise it's the second element
if i == 1 {
questionAuthor = s.Text()
questionAuthorURL, _ = s.Attr("href")
return
}
})
@@ -213,17 +230,17 @@ func ViewQuestion(c *gin.Context) {
answerFooter := s.Find("div.mt24")
answerAuthorURL := ""
answerAuthorURL := fmt.Sprintf("https://%s", domain)
answerAuthorName := ""
answerTimestamp := ""
answerFooter.Find("div.post-signature").Each(func(i int, s *goquery.Selection) {
questionAuthorDetails := questionMetadata.Find("div.user-details")
answerAuthorDetails := s.Find("div.user-details")
if questionAuthorDetails.Length() > 0 {
questionAuthor := questionAuthorDetails.Find("a").First()
newFilteredQuestion.AuthorName = html.EscapeString(questionAuthor.Text())
newFilteredQuestion.AuthorURL = html.EscapeString(questionAuthor.AttrOr("href", ""))
if answerAuthorDetails.Length() > 0 {
questionAuthor := answerAuthorDetails.Find("a").First()
answerAuthorName = html.EscapeString(questionAuthor.Text())
answerAuthorURL += html.EscapeString(questionAuthor.AttrOr("href", ""))
}
answerTimestamp = html.EscapeString(s.Find("span.relativetime").Text())
@@ -248,7 +265,7 @@ func ViewQuestion(c *gin.Context) {
answerBodyHTML = strings.Replace(answerBodyHTML, codeBlock, highlightedCodeBlock, 1)
}
comments = utils.FindAndReturnComments(answerBodyHTML, postLayout)
comments = utils.FindAndReturnComments(answerBodyHTML, domain, postLayout)
newFilteredAnswer.Comments = comments
newFilteredAnswer.Body = template.HTML(utils.ReplaceImgTags(answerBodyHTML))
@@ -269,6 +286,7 @@ func ViewQuestion(c *gin.Context) {
"theme": c.MustGet("theme").(string),
"currentUrl": fmt.Sprintf("%s/questions/%s/%s", os.Getenv("APP_URL"), questionId, questionTitle),
"sortValue": sortValue,
"domain": domain,
})
}
+4 -3
View File
@@ -2,12 +2,13 @@ package utils
import (
"anonymousoverflow/src/types"
"fmt"
"html/template"
"github.com/PuerkitoBio/goquery"
)
func FindAndReturnComments(inHtml string, postLayout *goquery.Selection) (comments []types.FilteredComment) {
func FindAndReturnComments(inHtml, domain string, postLayout *goquery.Selection) (comments []types.FilteredComment) {
commentsComponent := postLayout.Find("div.js-post-comments-component")
@@ -34,7 +35,7 @@ func FindAndReturnComments(inHtml string, postLayout *goquery.Selection) (commen
return
}
commentAuthorURL := ""
commentAuthorURL := fmt.Sprintf("https://%s", domain)
commentAuthor := commentBody.Find("span.comment-user")
if commentAuthor.Length() == 0 {
@@ -43,7 +44,7 @@ func FindAndReturnComments(inHtml string, postLayout *goquery.Selection) (commen
return
}
commentAuthorURL = commentAuthor.AttrOr("href", "")
commentAuthorURL += commentAuthor.AttrOr("href", "")
}
commentTimestamp := commentBody.Find("span.relativetime-clean").Text()
+1 -1
View File
@@ -19,7 +19,7 @@
<div class="comment-author">
Commented {{ $comment.Timestamp }} by
<a
href="https://stackoverflow.com{{ $comment.AuthorURL }}"
href="{{ $comment.AuthorURL }}"
target="_blank"
rel="noopener noreferrer"
>{{ $comment.AuthorName }}</a
+2 -2
View File
@@ -30,7 +30,7 @@
<p class="timestamp">
Asked {{ .question.Timestamp }} by
<a
href="https://stackoverflow.com{{ .question.AuthorURL }}"
href="{{ .question.AuthorURL }}"
target="_blank"
rel="noopener noreferrer"
>{{ .question.AuthorName }}</a
@@ -87,7 +87,7 @@
<div class="answer-author">
Answered {{ $answer.Timestamp }} by
<a
href="https://stackoverflow.com{{ $answer.AuthorURL }}"
href="{{ $answer.AuthorURL }}"
target="_blank"
rel="noopener noreferrer"
>{{ $answer.AuthorName }}</a