diff options
Diffstat (limited to 'comments.go')
| -rw-r--r-- | comments.go | 85 |
1 files changed, 64 insertions, 21 deletions
diff --git a/comments.go b/comments.go index 1bb1f99..6e41f38 100644 --- a/comments.go +++ b/comments.go @@ -4,18 +4,28 @@ import ( "encoding/json" "net/url" "strconv" + "strings" ) +// Thread is a single comment, despite the name. Replies are not nested inside +// it: a thread arrives flattened into [Comments].Thread, and the shape is +// recovered through Parent, which holds the ID of the comment being replied to +// and is 0 for a top-level comment. type Thread struct { Replies, Likes int ID int `json:"commentId"` Parent int `json:"parentId"` Posted timeStamp + // Author reports whether the commenter is the author of the deviation being + // commented on. Author bool `json:"isAuthorHighlited"` Desctiption string - Comment string + + // Comment is the comment's plain text, which [GetComments] extracts from + // TextContent. Prefer it; TextContent is the unprocessed original. + Comment string TextContent Text @@ -25,6 +35,10 @@ type Thread struct { } } +// Comments is one page of comments. Thread holds the comments themselves, +// flattened rather than nested; Total counts every comment on the item, not just +// this page. Cursor resumes from the end of this page and HasMore reports +// whether anything remains. type Comments struct { Cursor string PrevOffset int @@ -34,7 +48,17 @@ type Comments struct { Thread []Thread } -// 1 - комментарии поста; 4 - комментарии на стене группы или пользователя +// GetComments retrieves comments on an item, 50 per page, with each comment's +// plain text extracted into [Thread].Comment. +// +// typ selects what postid refers to: 1 for comments on a deviation, 4 for those +// on a user's or group's profile wall. cursor resumes from a previous call's +// [Comments].Cursor; pass an empty string to start from the newest comment. +// +// page is an offset from cursor rather than an absolute page number, and it is +// walked one request at a time: page 5 costs six round-trips and returns only +// the sixth page. Paginating by feeding each result's Cursor back in with page 0 +// costs one request per page, and is the cheaper way to walk a long thread. func GetComments(postid string, cursor string, page int, typ int) (cmmts Comments, err Error) { for x := 0; x <= page; x++ { err = ujson( @@ -46,28 +70,47 @@ func GetComments(postid string, cursor string, page int, typ int) (cmmts Comment cursor = cmmts.Cursor - // парсинг json внутри json for i := 0; i < len(cmmts.Thread); i++ { - m, l := cmmts.Thread[i].TextContent.Html.Markup, len(cmmts.Thread[i].TextContent.Html.Markup) - cmmts.Thread[i].Comment = m - - // если начало строки {, а конец }, то срабатывает этот иф - if m[0] == '{' && m[l-1] == '}' { - var content struct { - Blocks []struct { - Text string - } - } - - e := json.Unmarshal([]byte(m), &content) - try(e) - - for _, a := range content.Blocks { - cmmts.Thread[i].Comment = a.Text - } - } + cmmts.Thread[i].Comment = flattenComment(cmmts.Thread[i].TextContent.Html.Markup) } } return } + +// flattenComment renders a body of user-written markup as plain text, be it a +// comment or a deviation's description. Bodies are JSON inside JSON: newer ones +// are a Draft.js document encoded into the markup string, older ones are plain +// HTML, which passes through unchanged. Markup that does not parse, and empty +// markup, also pass through. +// +// A Draft.js document is a list of blocks, which are block-level elements +// (paragraphs, list items); they are joined with newlines, one block per line. +func flattenComment(m string) string { + l := len(m) + if l == 0 || m[0] != '{' || m[l-1] != '}' { + return m + } + + var content struct { + Blocks []struct { + Text string + } + } + + e := json.Unmarshal([]byte(m), &content) + try(e) + + if len(content.Blocks) == 0 { + return m + } + + var b strings.Builder + for i, a := range content.Blocks { + if i > 0 { + b.WriteString("\n") + } + b.WriteString(a.Text) + } + return b.String() +} |
