@@ -27,6 +27,38 @@ interface ParserResult {
2727 meta : string ;
2828}
2929
30+ interface SearchResponse {
31+ query : string ;
32+ locale : string ;
33+ page : number ;
34+ pages : number ;
35+ starts : number ;
36+ end : number ;
37+ next : string ;
38+ previous : string | null ;
39+ count : number ;
40+ filter : Array < {
41+ name : string ;
42+ slug : string ;
43+ options : Array < {
44+ name : string ;
45+ slug : string ;
46+ count : number ;
47+ active : boolean ;
48+ urls : {
49+ active : string ;
50+ inactive : string ;
51+ } ;
52+ } > ;
53+ } > ;
54+ documents : Array < {
55+ title : string ;
56+ slug : string ;
57+ locale : string ;
58+ excerpt : string ;
59+ } > ;
60+ }
61+
3062interface ResultMeta {
3163 getElementsByClassName ( cls : string ) : DOMParser . Node [ ] ;
3264}
@@ -75,6 +107,65 @@ const extractMetadataFromResult = (result: ResultMeta) => {
75107 } ;
76108} ;
77109
110+ export const updatedQueryBuilder = (
111+ searchUrl : typeof getSearchUrl = getSearchUrl ,
112+ fetch : typeof useData = useData ,
113+ waitForChosenResult : typeof getChosenResult = getChosenResult
114+ ) => async ( msg : Message , searchTerm : string ) => {
115+ const url = searchUrl ( provider , searchTerm ) ;
116+ const { error, json } = await fetch < SearchResponse > ( url , 'json' ) ;
117+ if ( ! error ) {
118+ return msg . reply ( errors . invalidResponse ) ;
119+ }
120+
121+ if ( json . documents . length === 0 ) {
122+ const sentMsg = await msg . reply ( errors . noResults ( searchTerm ) ) ;
123+ return delayedMessageAutoDeletion ( sentMsg ) ;
124+ }
125+
126+ let preparedDescription = json . documents . map (
127+ ( { title, excerpt, slug } , index ) =>
128+ createMarkdownListItem (
129+ index ,
130+ createMarkdownLink (
131+ adjustTitleLength ( [ `**${ title } **` , excerpt ] . join ( ' - ' ) ) ,
132+ buildDirectUrl ( provider , slug )
133+ )
134+ )
135+ ) ;
136+
137+ const expectedLength = preparedDescription . reduce (
138+ ( sum , item ) => sum + item . length ,
139+ 0
140+ ) ;
141+ if ( expectedLength + BASE_DESCRIPTION . length + 10 * '\n' . length > 2048 ) {
142+ preparedDescription = preparedDescription . map ( string => {
143+ // split at markdown link ending
144+ const [ title , ...rest ] = string . split ( '...]' ) ;
145+
146+ // split title on title - excerpt glue
147+ // concat with rest
148+ // fix broken markdown link ending
149+ return [ title . split ( ' - ' ) [ 0 ] , rest . join ( '' ) ] . join ( ']' ) ;
150+ } ) ;
151+ }
152+
153+ const sentMsg = await msg . channel . send (
154+ createListEmbed ( {
155+ description : createDescription ( preparedDescription ) ,
156+ footerText : 'Powered by the search API' ,
157+ provider,
158+ searchTerm,
159+ url,
160+ } )
161+ ) ;
162+
163+ const result = await waitForChosenResult ( sentMsg , msg , json . documents ) ;
164+ if ( ! result ) {
165+ return ;
166+ }
167+ } ;
168+
78169/**
79170 * Poor man's dependency injection without introducing classes, just use closures
80171 * and higher order functions instead. Also provides a default so we don't have
0 commit comments