@microlink/google 0.0.0 → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/src/index.d.ts ADDED
@@ -0,0 +1,327 @@
1
+ type Period = 'hour' | 'day' | 'week' | 'month' | 'year'
2
+
3
+ type Type =
4
+ | 'search'
5
+ | 'news'
6
+ | 'images'
7
+ | 'videos'
8
+ | 'places'
9
+ | 'maps'
10
+ | 'shopping'
11
+ | 'scholar'
12
+ | 'patents'
13
+ | 'autocomplete'
14
+
15
+ interface TypeToPage {
16
+ search: SearchPage
17
+ news: NewsPage
18
+ images: ImagesPage
19
+ videos: VideosPage
20
+ places: PlacesPage
21
+ maps: MapsPage
22
+ shopping: ShoppingPage
23
+ scholar: ScholarPage
24
+ patents: PatentsPage
25
+ autocomplete: AutocompletePage
26
+ }
27
+
28
+ type Location =
29
+ | 'af' | 'al' | 'dz' | 'as' | 'ad' | 'ao' | 'ai' | 'aq' | 'ag' | 'ar'
30
+ | 'am' | 'aw' | 'au' | 'at' | 'az' | 'bs' | 'bh' | 'bd' | 'bb' | 'by'
31
+ | 'be' | 'bz' | 'bj' | 'bm' | 'bt' | 'bo' | 'ba' | 'bw' | 'bv' | 'br'
32
+ | 'io' | 'bn' | 'bg' | 'bf' | 'bi' | 'kh' | 'cm' | 'ca' | 'cv' | 'ky'
33
+ | 'cf' | 'td' | 'cl' | 'cn' | 'cx' | 'cc' | 'co' | 'km' | 'cg' | 'cd'
34
+ | 'ck' | 'cr' | 'ci' | 'hr' | 'cu' | 'cy' | 'cz' | 'dk' | 'dj' | 'dm'
35
+ | 'do' | 'ec' | 'eg' | 'sv' | 'gq' | 'er' | 'ee' | 'et' | 'fk' | 'fo'
36
+ | 'fj' | 'fi' | 'fr' | 'gf' | 'pf' | 'tf' | 'ga' | 'gm' | 'ge' | 'de'
37
+ | 'gh' | 'gi' | 'gr' | 'gl' | 'gd' | 'gp' | 'gu' | 'gt' | 'gn' | 'gw'
38
+ | 'gy' | 'ht' | 'hm' | 'va' | 'hn' | 'hk' | 'hu' | 'is' | 'in' | 'id'
39
+ | 'ir' | 'iq' | 'ie' | 'il' | 'it' | 'jm' | 'jp' | 'jo' | 'kz' | 'ke'
40
+ | 'ki' | 'kp' | 'kr' | 'kw' | 'kg' | 'la' | 'lv' | 'lb' | 'ls' | 'lr'
41
+ | 'ly' | 'li' | 'lt' | 'lu' | 'mo' | 'mk' | 'mg' | 'mw' | 'my' | 'mv'
42
+ | 'ml' | 'mt' | 'mh' | 'mq' | 'mr' | 'mu' | 'yt' | 'mx' | 'fm' | 'md'
43
+ | 'mc' | 'mn' | 'ms' | 'ma' | 'mz' | 'mm' | 'na' | 'nr' | 'np' | 'nl'
44
+ | 'an' | 'nc' | 'nz' | 'ni' | 'ne' | 'ng' | 'nu' | 'nf' | 'mp' | 'no'
45
+ | 'om' | 'pk' | 'pw' | 'ps' | 'pa' | 'pg' | 'py' | 'pe' | 'ph' | 'pn'
46
+ | 'pl' | 'pt' | 'pr' | 'qa' | 're' | 'ro' | 'ru' | 'rw' | 'sh' | 'kn'
47
+ | 'lc' | 'pm' | 'vc' | 'ws' | 'sm' | 'st' | 'sa' | 'sn' | 'rs' | 'sc'
48
+ | 'sl' | 'sg' | 'sk' | 'si' | 'sb' | 'so' | 'za' | 'gs' | 'es' | 'lk'
49
+ | 'sd' | 'sr' | 'sj' | 'sz' | 'se' | 'ch' | 'sy' | 'tw' | 'tj' | 'tz'
50
+ | 'th' | 'tl' | 'tg' | 'tk' | 'to' | 'tt' | 'tn' | 'tr' | 'tm' | 'tc'
51
+ | 'tv' | 'ug' | 'ua' | 'ae' | 'gb' | 'us' | 'um' | 'uy' | 'uz' | 'vu'
52
+ | 've' | 'vn' | 'vg' | 'vi' | 'wf' | 'eh' | 'ye' | 'zm' | 'zw'
53
+
54
+ interface Options {
55
+ type?: Type
56
+ limit?: number
57
+ location?: Location
58
+ period?: Period
59
+ }
60
+
61
+ interface Sitelink {
62
+ title: string
63
+ link: string
64
+ }
65
+
66
+ interface KnowledgeGraph {
67
+ title?: string
68
+ type?: string
69
+ website?: string
70
+ image?: { url: string }
71
+ description?: string
72
+ descriptionSource?: string
73
+ descriptionLink?: string
74
+ attributes?: Record<string, string>
75
+ }
76
+
77
+ interface PeopleAlsoAsk {
78
+ question: string
79
+ snippet: string
80
+ title: string
81
+ link: string
82
+ }
83
+
84
+ interface RelatedSearch {
85
+ query: string
86
+ }
87
+
88
+ interface SearchResult {
89
+ title: string
90
+ url: string
91
+ description: string
92
+ html(): Promise<string>
93
+ markdown(): Promise<string>
94
+ }
95
+
96
+ interface SearchPage {
97
+ results: SearchResult[]
98
+ knowledgeGraph?: KnowledgeGraph
99
+ peopleAlsoAsk?: PeopleAlsoAsk[]
100
+ relatedSearches?: RelatedSearch[]
101
+ html(): Promise<string>
102
+ markdown(): Promise<string>
103
+ next(): Promise<SearchPage>
104
+ }
105
+
106
+ interface NewsResult {
107
+ title: string
108
+ url: string
109
+ description: string
110
+ date: string
111
+ publisher: string
112
+ image?: { url: string }
113
+ html(): Promise<string>
114
+ markdown(): Promise<string>
115
+ }
116
+
117
+ interface NewsPage {
118
+ results: NewsResult[]
119
+ html(): Promise<string>
120
+ markdown(): Promise<string>
121
+ next(): Promise<NewsPage>
122
+ }
123
+
124
+ interface ImageResult {
125
+ title: string
126
+ url: string
127
+ image: { url: string; width: number; height: number }
128
+ thumbnail: { url: string; width: number; height: number }
129
+ google?: { url: string }
130
+ creator?: string
131
+ credit?: string
132
+ html(): Promise<string>
133
+ markdown(): Promise<string>
134
+ }
135
+
136
+ interface ImagesPage {
137
+ results: ImageResult[]
138
+ html(): Promise<string>
139
+ markdown(): Promise<string>
140
+ next(): Promise<ImagesPage>
141
+ }
142
+
143
+ interface VideoResult {
144
+ title: string
145
+ url: string
146
+ description: string
147
+ image?: { url: string }
148
+ video?: { url: string }
149
+ duration?: number
150
+ duration_pretty?: string
151
+ publisher?: string
152
+ channel?: string
153
+ date?: string
154
+ html(): Promise<string>
155
+ markdown(): Promise<string>
156
+ }
157
+
158
+ interface VideosPage {
159
+ results: VideoResult[]
160
+ html(): Promise<string>
161
+ markdown(): Promise<string>
162
+ next(): Promise<VideosPage>
163
+ }
164
+
165
+ interface PlaceResult {
166
+ title: string
167
+ address: string
168
+ latitude: number
169
+ longitude: number
170
+ phone?: { number: string }
171
+ url?: string
172
+ cid: string
173
+ html(): Promise<string>
174
+ markdown(): Promise<string>
175
+ }
176
+
177
+ interface PlacesPage {
178
+ results: PlaceResult[]
179
+ html(): Promise<string>
180
+ markdown(): Promise<string>
181
+ next(): Promise<PlacesPage>
182
+ }
183
+
184
+ interface MapPlaceResult {
185
+ title: string
186
+ address: string
187
+ latitude: number
188
+ longitude: number
189
+ rating?: number
190
+ ratingCount?: number
191
+ price?: { level: string }
192
+ type?: string
193
+ types?: string[]
194
+ url?: string
195
+ phone?: { number: string }
196
+ description?: string
197
+ opening?: { hours: Record<string, string> }
198
+ thumbnail?: { url: string }
199
+ cid: string
200
+ fid?: string
201
+ place?: { id: string }
202
+ html(): Promise<string>
203
+ markdown(): Promise<string>
204
+ }
205
+
206
+ interface MapsPage {
207
+ results: MapPlaceResult[]
208
+ html(): Promise<string>
209
+ markdown(): Promise<string>
210
+ next(): Promise<MapsPage>
211
+ }
212
+
213
+ interface ShoppingResult {
214
+ title: string
215
+ url: string
216
+ publisher: string
217
+ price: { symbol: string; amount: number }
218
+ image?: { url: string }
219
+ rating?: { score: number; total: number; reviews?: number }
220
+ id?: string
221
+ html(): Promise<string>
222
+ markdown(): Promise<string>
223
+ }
224
+
225
+ interface ShoppingPage {
226
+ results: ShoppingResult[]
227
+ html(): Promise<string>
228
+ markdown(): Promise<string>
229
+ next(): Promise<ShoppingPage>
230
+ }
231
+
232
+ interface ScholarResult {
233
+ title: string
234
+ url: string
235
+ description: string
236
+ publisher: string
237
+ year: number
238
+ citations: number
239
+ pdf?: { url: string }
240
+ id: string
241
+ html(): Promise<string>
242
+ markdown(): Promise<string>
243
+ }
244
+
245
+ interface ScholarPage {
246
+ results: ScholarResult[]
247
+ html(): Promise<string>
248
+ markdown(): Promise<string>
249
+ next(): Promise<ScholarPage>
250
+ }
251
+
252
+ interface PatentResult {
253
+ title: string
254
+ description: string
255
+ url: string
256
+ priority: { date: string }
257
+ filing: { date: string }
258
+ grant?: { date: string }
259
+ publication: { date: string; number: string }
260
+ inventor: string
261
+ assignee: string
262
+ language: string
263
+ pdf?: { url: string }
264
+ thumbnail?: { url: string }
265
+ figures?: Array<{ image: { url: string }; thumbnail: { url: string } }>
266
+ id?: string
267
+ html(): Promise<string>
268
+ markdown(): Promise<string>
269
+ }
270
+
271
+ interface PatentsPage {
272
+ results: PatentResult[]
273
+ html(): Promise<string>
274
+ markdown(): Promise<string>
275
+ next(): Promise<PatentsPage>
276
+ }
277
+
278
+ interface SuggestionResult {
279
+ value: string
280
+ }
281
+
282
+ interface AutocompletePage {
283
+ results: SuggestionResult[]
284
+ html(): Promise<string>
285
+ markdown(): Promise<string>
286
+ next(): Promise<AutocompletePage>
287
+ }
288
+
289
+ interface GoogleClient {
290
+ <K extends Type>(
291
+ query: string,
292
+ options: Omit<Options, 'type'> & { type: K }
293
+ ): Promise<TypeToPage[K]>
294
+ (query: string, options?: Options): Promise<SearchPage>
295
+ }
296
+
297
+ interface ContextOptions {
298
+ apiKey?: string
299
+ endpoint?: string
300
+ timeout?: number
301
+ }
302
+
303
+ export declare const DOMAIN: string
304
+
305
+ export declare function buildPath(
306
+ query: string,
307
+ limit?: number,
308
+ location?: string
309
+ ): string
310
+
311
+ export declare function buildUrl(
312
+ query: string,
313
+ options?: {
314
+ limit?: number
315
+ location?: string
316
+ type?: Type
317
+ period?: Period
318
+ }
319
+ ): URL
320
+
321
+ interface createGoogleClient {
322
+ (options?: ContextOptions): GoogleClient
323
+ }
324
+
325
+ declare const createGoogleClient: createGoogleClient
326
+
327
+ export default createGoogleClient
package/src/index.js CHANGED
@@ -4,51 +4,77 @@ const mql = require('@microlink/mql')
4
4
 
5
5
  const DOMAIN = 'microlink.google'
6
6
 
7
- const buildPath = (query, limit, lang) =>
8
- [encodeURIComponent(query).replace(/%20/g, '+'), limit, lang]
7
+ const buildPath = (query, limit, location) =>
8
+ [encodeURIComponent(query).replace(/%20/g, '+'), limit, location]
9
9
  .filter(v => v !== undefined)
10
10
  .join('/')
11
11
 
12
- const buildUrl = (query, { limit, lang, device, period, domain } = {}) => {
13
- const url = new URL(`https://${DOMAIN}/${buildPath(query, limit, lang)}`)
14
- if (device) url.searchParams.set('device', device)
12
+ const buildUrl = (query, { limit, location, type, period } = {}) => {
13
+ const url = new URL(`https://${DOMAIN}/${buildPath(query, limit, location)}`)
14
+ if (type) url.searchParams.set('type', type)
15
15
  if (period) url.searchParams.set('period', period)
16
- if (domain) url.searchParams.set('domain', domain)
17
16
  return url
18
17
  }
19
18
 
20
- const fetchPage = async (url, mqlOpts, offset) => {
19
+ const resultUrl = result => result.url
20
+
21
+ const fetchDataField = async (url, mqlOpts, field, attr) => {
22
+ const { data } = await mql(url, {
23
+ ...mqlOpts,
24
+ data: { [field]: { attr } }
25
+ })
26
+ return data[field]
27
+ }
28
+
29
+ const fetchPage = async (url, mqlOpts, offset, query) => {
21
30
  url.searchParams.set('start', String(offset))
22
31
  const { data } = await mql(url.toString(), mqlOpts)
23
- const { results, html } = data
32
+ const { results, ...extra } = data
24
33
 
25
34
  return {
26
- html: () => Promise.resolve(html),
27
- results: results.map(result => ({
28
- ...result,
29
- html: async () => {
30
- const { data } = await mql(result.url, {
31
- ...mqlOpts,
32
- data: { content: { attr: 'html' } }
35
+ ...extra,
36
+ html: () =>
37
+ fetchDataField(
38
+ `https://www.google.com/search?q=${encodeURIComponent(query)}`,
39
+ mqlOpts,
40
+ 'content',
41
+ 'html'
42
+ ),
43
+ markdown: () =>
44
+ fetchDataField(
45
+ `https://www.google.com/search?q=${encodeURIComponent(query)}`,
46
+ mqlOpts,
47
+ 'markdown',
48
+ 'markdown'
49
+ ),
50
+ results: results.map(result => {
51
+ const url = resultUrl(result)
52
+ return {
53
+ ...result,
54
+ ...(url && {
55
+ html: () => fetchDataField(url, mqlOpts, 'content', 'html'),
56
+ markdown: () => fetchDataField(url, mqlOpts, 'markdown', 'markdown')
33
57
  })
34
- return data.content
35
58
  }
36
- })),
59
+ }),
37
60
  next: () =>
38
- fetchPage(new URL(url.toString()), mqlOpts, offset + results.length)
61
+ fetchPage(
62
+ new URL(url.toString()),
63
+ mqlOpts,
64
+ offset + results.length,
65
+ query
66
+ )
39
67
  }
40
68
  }
41
69
 
42
- module.exports = ctxOpts => {
43
- return async (
44
- query,
45
- { limit, lang, device, period, domain, ...opts } = {}
46
- ) => {
47
- const url = buildUrl(query, { limit, lang, device, period, domain })
48
- return fetchPage(url, { ...ctxOpts, ...opts }, 0)
70
+ const createGoogleClient = ctxOpts => {
71
+ return async (query, { limit, location, type, period, ...opts } = {}) => {
72
+ const url = buildUrl(query, { limit, location, type, period })
73
+ return fetchPage(url, { ...ctxOpts, ...opts }, 0, query)
49
74
  }
50
75
  }
51
76
 
77
+ module.exports = createGoogleClient
52
78
  module.exports.buildPath = buildPath
53
79
  module.exports.buildUrl = buildUrl
54
80
  module.exports.DOMAIN = DOMAIN