@@ -27,10 +27,20 @@ const (
2727)
2828
2929func truncateText (s string , max int ) string {
30+ if s == "" {
31+ return "Documentation available - click to view"
32+ }
3033 if max > len (s ) {
3134 return s
3235 }
33- return s [:strings .LastIndex (s [:max ], " " )] + " ..."
36+
37+ // Find last space before max length
38+ truncated := s [:max ]
39+ if lastSpace := strings .LastIndex (truncated , " " ); lastSpace > max / 2 {
40+ return truncated [:lastSpace ] + "..."
41+ }
42+
43+ return truncated + "..."
3444}
3545
3646func (cm * CommandManager ) commandWiki (
@@ -61,7 +71,7 @@ func (cm *CommandManager) commandWiki(
6171 search .NewEmptySearchForHits ().
6272 SetIndexName (algoliaIndexName ).
6373 SetQuery (searchTerm ).
64- SetHitsPerPage (3 ).
74+ SetHitsPerPage (5 ).
6575 SetFilters ("language:en" ),
6676 )},
6777 ),
@@ -78,6 +88,7 @@ func (cm *CommandManager) commandWiki(
7888 Type : discordgo .EmbedTypeRich ,
7989 Title : fmt .Sprintf ("No results: %s" , searchTerm ),
8090 Description : "There were no results for that query." ,
91+ Color : 0xED4245 , // Red color for no results
8192 })
8293 return
8394 }
@@ -102,61 +113,194 @@ func (cm *CommandManager) commandWiki(
102113 continue
103114 }
104115
105- if seenUrls [hitData ["url_without_anchor" ].(string )] { //Already presented to user - Algolia does this thing of sending twice the same thing
116+ // Get URL
117+ urlWithoutAnchor , ok := hitData ["url_without_anchor" ].(string )
118+ if ! ok {
106119 continue
107120 }
108121
109- seenUrls [hitData ["url_without_anchor" ].(string )] = true
122+ // Skip if already processed this URL - Algolia does this thing of sending twice the same thing
123+ if seenUrls [urlWithoutAnchor ] {
124+ continue
125+ }
126+ seenUrls [urlWithoutAnchor ] = true
110127
111- stringParts := strings .Split (strings .TrimSuffix (hitData ["url_without_anchor" ].(string ), "/" ), "/" ) //Algolia doesnt give the Function/Callback name - so I steal it from the URL
128+ // Parse URL to get page info - Algolia doesn't give the Function/Callback name - so I steal it from the URL
129+ stringParts := strings .Split (strings .TrimSuffix (urlWithoutAnchor , "/" ), "/" )
130+ if len (stringParts ) < 3 {
131+ continue
132+ }
112133
113- if stringParts [len (stringParts )- 2 ] == "blog" { //Remove blog posts from results
134+ // Skip blog posts and other non-documentation pages - Remove blog posts from results
135+ if len (stringParts ) >= 4 && (stringParts [len (stringParts )- 2 ] == "blog" ||
136+ stringParts [len (stringParts )- 3 ] == "blog" ) {
114137 continue
115138 }
116139
117140 actuallyFoundResults ++
118141
119- content , ok := hitData ["content" ].(string )
120- description := ""
121- if ! ok {
122- description = "(No description found)"
123- } else {
124- description = formatDescription (& content )
125- }
142+ // Get page/function name
143+ pageName := stringParts [len (stringParts )- 1 ]
144+
145+ // Get description from multiple possible sources
146+ description := extractDescription (hitData )
147+
148+ // Build category path
149+ category := buildCategory (stringParts )
126150
151+ // Format the result
127152 desc .WriteString (fmt .Sprintf (
128- "[%s](%s) [%s/%s]: %s\n " ,
129- stringParts [len (stringParts )- 1 ],
130- hitData ["url_without_anchor" ].(string ),
131- stringParts [len (stringParts )- 3 ],
132- stringParts [len (stringParts )- 2 ],
133- truncateText (description , 200 ),
153+ "[**%s**](%s)\n %s: %s\n \n " ,
154+ pageName ,
155+ urlWithoutAnchor ,
156+ category ,
157+ truncateText (description , 120 ),
134158 ))
159+
160+ // Limit to 3 results for readability
161+ if actuallyFoundResults >= 3 {
162+ break
163+ }
135164 }
136165
137- if actuallyFoundResults == 0 { //Hitting this means all results were filtered out
166+ // Hitting this means all results were filtered out
167+ if actuallyFoundResults == 0 {
138168 cm .replyDirectlyEmbed (interaction , "" , & discordgo.MessageEmbed {
139169 Type : discordgo .EmbedTypeRich ,
140170 Title : fmt .Sprintf ("No results: %s" , searchTerm ),
141- Description : "There were no results for that query." ,
171+ Description : "No documentation found for that query. Try a different search term." ,
172+ Color : 0xED4245 ,
142173 })
143174 return
144175 }
145176
146177 embed := & discordgo.MessageEmbed {
147178 Type : discordgo .EmbedTypeRich ,
148- Title : fmt .Sprintf ("Documentation Search Results: %s" , searchTerm ),
179+ Title : fmt .Sprintf ("Documentation Search Results for %s" , searchTerm ),
149180 Description : desc .String (),
181+ Color : 0x5865F2 , // Discord blurple
182+ Footer : & discordgo.MessageEmbedFooter {
183+ Text : "Click the links to view full documentation" ,
184+ },
150185 }
151186 cm .replyDirectlyEmbed (interaction , "" , embed )
152187
153- return false , err // Todo: remove this
188+ return false , err
189+ }
190+
191+ func extractDescription (hitData map [string ]interface {}) string {
192+ // Try to get description from various fields in order of preference
193+ descriptionSources := []string {
194+ "description" , // Most likely to have the frontmatter description
195+ "content" , // Page content
196+ "excerpt" , // Page excerpt
197+ "text" , // Text content
198+ "summary" , // Summary
199+ }
200+
201+ for _ , field := range descriptionSources {
202+ if value , exists := hitData [field ]; exists {
203+ if strValue , ok := value .(string ); ok && strings .TrimSpace (strValue ) != "" {
204+ cleaned := cleanDescription (strValue )
205+ if cleaned != "" {
206+ return cleaned
207+ }
208+ }
209+ }
210+ }
211+
212+ // Try hierarchy for context
213+ if hierarchy , exists := hitData ["hierarchy" ]; exists {
214+ if hierarchyMap , ok := hierarchy .(map [string ]interface {}); ok {
215+ // Try different hierarchy levels
216+ for _ , level := range []string {"lvl0" , "lvl1" , "lvl2" , "lvl3" } {
217+ if lvlValue , exists := hierarchyMap [level ]; exists {
218+ if strValue , ok := lvlValue .(string ); ok && strings .TrimSpace (strValue ) != "" {
219+ return cleanDescription (strValue )
220+ }
221+ }
222+ }
223+ }
224+ }
225+
226+ // Try anchor text
227+ if anchor , exists := hitData ["anchor" ]; exists {
228+ if strValue , ok := anchor .(string ); ok && strings .TrimSpace (strValue ) != "" {
229+ return cleanDescription (strValue )
230+ }
231+ }
232+
233+ return "Documentation available"
154234}
155235
156- func formatDescription (hit * string ) string {
157- return html .UnescapeString (strings .ReplaceAll (
158- strings .ReplaceAll (
159- * hit ,
160- "<mark>" , "**" ),
161- "</mark>" , "**" ))
236+ func cleanDescription (text string ) string {
237+ if text == "" {
238+ return ""
239+ }
240+
241+ // Remove HTML tags and decode entities
242+ cleaned := html .UnescapeString (text )
243+
244+ // Remove markdown-style highlighting
245+ cleaned = strings .ReplaceAll (cleaned , "<mark>" , "**" )
246+ cleaned = strings .ReplaceAll (cleaned , "</mark>" , "**" )
247+
248+ // Clean up whitespace and newlines
249+ cleaned = strings .ReplaceAll (cleaned , "\n " , " " )
250+ cleaned = strings .ReplaceAll (cleaned , "\r " , " " )
251+
252+ // Remove multiple spaces
253+ for strings .Contains (cleaned , " " ) {
254+ cleaned = strings .ReplaceAll (cleaned , " " , " " )
255+ }
256+
257+ cleaned = strings .TrimSpace (cleaned )
258+
259+ // Remove common prefixes that aren't useful
260+ prefixesToRemove := []string {
261+ "Description:" ,
262+ "Description" ,
263+ "## Description" ,
264+ "###" ,
265+ "##" ,
266+ "#" ,
267+ }
268+
269+ for _ , prefix := range prefixesToRemove {
270+ if strings .HasPrefix (cleaned , prefix ) {
271+ cleaned = strings .TrimSpace (strings .TrimPrefix (cleaned , prefix ))
272+ }
273+ }
274+
275+ return cleaned
162276}
277+
278+ func buildCategory (urlParts []string ) string {
279+ if len (urlParts ) < 4 {
280+ return "Documentation"
281+ }
282+
283+ // Extract meaningful category parts
284+ var categoryParts []string
285+
286+ // Skip the domain parts and get the meaningful path
287+ for i := 3 ; i < len (urlParts )- 1 ; i ++ {
288+ part := urlParts [i ]
289+
290+ // Skip common path parts that aren't useful
291+ if part == "docs" || part == "en" || part == "" {
292+ continue
293+ }
294+
295+ // Capitalize and clean up the part
296+ part = strings .ReplaceAll (part , "-" , " " )
297+ part = strings .Title (part )
298+ categoryParts = append (categoryParts , part )
299+ }
300+
301+ if len (categoryParts ) == 0 {
302+ return "Documentation"
303+ }
304+
305+ return strings .Join (categoryParts , " › " )
306+ }
0 commit comments