MCPcopy Create free account
hub / github.com/basecamp/hey-cli / ParseTopicEntriesHTML

Function ParseTopicEntriesHTML

internal/htmlutil/entries.go:70–135  ·  view source on GitHub ↗

ParseTopicEntriesHTML extracts structured entry data from the HTML page served by /topics/{id}/entries. The JSON API does not return full entry bodies, so this HTML-based extraction is required.

(html string)

Source from the content-addressed store, hash-verified

68// served by /topics/{id}/entries. The JSON API does not return full entry
69// bodies, so this HTML-based extraction is required.
70func ParseTopicEntriesHTML(html string) []models.Entry {
71 // Find unique entry IDs in order
72 idMatches := entryBlockRe.FindAllStringSubmatch(html, -1)
73 seen := map[string]bool{}
74 var entryIDs []string
75 for _, m := range idMatches {
76 if !seen[m[1]] {
77 seen[m[1]] = true
78 entryIDs = append(entryIDs, m[1])
79 }
80 }
81
82 // Build lookup maps
83 senders := map[string]string{}
84 for _, m := range senderRe.FindAllStringSubmatch(html, -1) {
85 if _, exists := senders[m[1]]; !exists {
86 senders[m[1]] = m[2]
87 }
88 }
89
90 // Associate times with entries by finding the first <time> after each entry anchor
91 entryTimes := map[string]string{}
92 for _, eid := range entryIDs {
93 anchor := fmt.Sprintf(`id="entry_%s"`, eid)
94 idx := strings.Index(html, anchor)
95 if idx < 0 {
96 continue
97 }
98 if m := timeRe.FindStringSubmatch(html[idx:]); m != nil {
99 entryTimes[eid] = m[1]
100 }
101 }
102
103 // Extract bodies from srcdoc iframes - they appear in entry order
104 type body struct{ html, text string }
105 bodyMatches := srcdocRe.FindAllStringSubmatch(html, -1)
106 bodies := make([]body, 0, len(bodyMatches))
107 for _, m := range bodyMatches {
108 raw := m[1]
109 raw = strings.ReplaceAll(raw, "&lt;", "<")
110 raw = strings.ReplaceAll(raw, "&gt;", ">")
111 raw = strings.ReplaceAll(raw, "&quot;", "\"")
112 raw = strings.ReplaceAll(raw, "&amp;", "&")
113 raw = strings.ReplaceAll(raw, "&#39;", "'")
114 bodies = append(bodies, body{html: raw, text: ToText(raw)})
115 }
116
117 entries := make([]models.Entry, 0, len(entryIDs))
118 for i, eid := range entryIDs {
119 id, _ := strconv.ParseInt(eid, 10, 64)
120 e := models.Entry{
121 ID: id,
122 CreatedAt: entryTimes[eid],
123 }
124 if name, ok := senders[eid]; ok {
125 e.Creator = models.Contact{Name: name}
126 }
127 if i < len(bodies) {

Callers 3

fetchTopicMethod · 0.92
runMethod · 0.92
runMethod · 0.92

Calls 1

ToTextFunction · 0.85

Tested by

no test coverage detected