123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146 |
- package feed
- import (
- "fmt"
- "html"
- "net/http"
- "net/url"
- "strings"
- "time"
- )
- type subredditResponseJson struct {
- Data struct {
- Children []struct {
- Data struct {
- Id string `json:"id"`
- Title string `json:"title"`
- Upvotes int `json:"ups"`
- Url string `json:"url"`
- Time float64 `json:"created"`
- CommentsCount int `json:"num_comments"`
- Domain string `json:"domain"`
- Permalink string `json:"permalink"`
- Stickied bool `json:"stickied"`
- Pinned bool `json:"pinned"`
- IsSelf bool `json:"is_self"`
- Thumbnail string `json:"thumbnail"`
- Flair string `json:"link_flair_text"`
- ParentList []struct {
- Id string `json:"id"`
- Subreddit string `json:"subreddit"`
- Permalink string `json:"permalink"`
- } `json:"crosspost_parent_list"`
- } `json:"data"`
- } `json:"children"`
- } `json:"data"`
- }
- func templateRedditCommentsURL(template, subreddit, postId, postPath string) string {
- template = strings.ReplaceAll(template, "{SUBREDDIT}", subreddit)
- template = strings.ReplaceAll(template, "{POST-ID}", postId)
- template = strings.ReplaceAll(template, "{POST-PATH}", strings.TrimLeft(postPath, "/"))
- return template
- }
- func FetchSubredditPosts(subreddit, sort, topPeriod, search, commentsUrlTemplate, requestUrlTemplate string, showFlairs bool) (ForumPosts, error) {
- query := url.Values{}
- var requestUrl string
- if search != "" {
- query.Set("q", search+" subreddit:"+subreddit)
- query.Set("sort", sort)
- }
- if sort == "top" {
- query.Set("t", topPeriod)
- }
- if search != "" {
- requestUrl = fmt.Sprintf("https://www.reddit.com/search.json?%s", query.Encode())
- } else {
- requestUrl = fmt.Sprintf("https://www.reddit.com/r/%s/%s.json?%s", subreddit, sort, query.Encode())
- }
- if requestUrlTemplate != "" {
- requestUrl = strings.ReplaceAll(requestUrlTemplate, "{REQUEST-URL}", requestUrl)
- }
- request, err := http.NewRequest("GET", requestUrl, nil)
- if err != nil {
- return nil, err
- }
- // Required to increase rate limit, otherwise Reddit randomly returns 429 even after just 2 requests
- addBrowserUserAgentHeader(request)
- responseJson, err := decodeJsonFromRequest[subredditResponseJson](defaultClient, request)
- if err != nil {
- return nil, err
- }
- if len(responseJson.Data.Children) == 0 {
- return nil, fmt.Errorf("no posts found")
- }
- posts := make(ForumPosts, 0, len(responseJson.Data.Children))
- for i := range responseJson.Data.Children {
- post := &responseJson.Data.Children[i].Data
- if post.Stickied || post.Pinned {
- continue
- }
- var commentsUrl string
- if commentsUrlTemplate == "" {
- commentsUrl = "https://www.reddit.com" + post.Permalink
- } else {
- commentsUrl = templateRedditCommentsURL(commentsUrlTemplate, subreddit, post.Id, post.Permalink)
- }
- forumPost := ForumPost{
- Title: html.UnescapeString(post.Title),
- DiscussionUrl: commentsUrl,
- TargetUrlDomain: post.Domain,
- CommentCount: post.CommentsCount,
- Score: post.Upvotes,
- TimePosted: time.Unix(int64(post.Time), 0),
- }
- if post.Thumbnail != "" && post.Thumbnail != "self" && post.Thumbnail != "default" && post.Thumbnail != "nsfw" {
- forumPost.ThumbnailUrl = html.UnescapeString(post.Thumbnail)
- }
- if !post.IsSelf {
- forumPost.TargetUrl = post.Url
- }
- if showFlairs && post.Flair != "" {
- forumPost.Tags = append(forumPost.Tags, post.Flair)
- }
- if len(post.ParentList) > 0 {
- forumPost.IsCrosspost = true
- forumPost.TargetUrlDomain = "r/" + post.ParentList[0].Subreddit
- if commentsUrlTemplate == "" {
- forumPost.TargetUrl = "https://www.reddit.com" + post.ParentList[0].Permalink
- } else {
- forumPost.TargetUrl = templateRedditCommentsURL(
- commentsUrlTemplate,
- post.ParentList[0].Subreddit,
- post.ParentList[0].Id,
- post.ParentList[0].Permalink,
- )
- }
- }
- posts = append(posts, forumPost)
- }
- return posts, nil
- }
|