tablefacts 0.1.0
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/.env.example +14 -0
- package/CHANGELOG.md +12 -0
- package/LICENSE +21 -0
- package/README.md +313 -0
- package/bin/tablefacts.mjs +28 -0
- package/package.json +77 -0
- package/src/index.mjs +52 -0
- package/src/instagram/README.md +135 -0
- package/src/instagram/download.mjs +62 -0
- package/src/instagram/index.mjs +355 -0
- package/src/instagram/links.mjs +55 -0
- package/src/instagram/record.mjs +18 -0
- package/src/lib/edge.mjs +49 -0
- package/src/lib/env.mjs +35 -0
- package/src/lib/errors.mjs +39 -0
- package/src/lib/files.mjs +10 -0
- package/src/lib/images.mjs +20 -0
- package/src/lib/log.mjs +17 -0
- package/src/lib/photos.mjs +42 -0
- package/src/lib/playwright.mjs +13 -0
- package/src/lib/project.mjs +42 -0
- package/src/lib/text.mjs +7 -0
- package/src/lib/types.mjs +247 -0
- package/src/menu/README.md +97 -0
- package/src/menu/cluvi/config.mjs +33 -0
- package/src/menu/cluvi/extract.mjs +24 -0
- package/src/menu/cluvi/import.mjs +30 -0
- package/src/menu/cluvi/source.mjs +156 -0
- package/src/menu/index.mjs +9 -0
- package/src/menu/lib/db.mjs +119 -0
- package/src/menu/lib/import.mjs +126 -0
- package/src/menu/lib/menu.mjs +95 -0
- package/src/menu/lib/run.mjs +83 -0
- package/src/menu/raw/config.mjs +38 -0
- package/src/menu/raw/extract.mjs +72 -0
- package/src/menu/raw/import.mjs +99 -0
- package/src/menu/raw/normalize.mjs +120 -0
- package/src/menu/raw/source.mjs +116 -0
- package/src/menu/raw/vision.mjs +252 -0
- package/src/research/README.md +69 -0
- package/src/research/index.mjs +147 -0
- package/src/research/lib/google.mjs +93 -0
- package/src/research/lib/hours.mjs +109 -0
- package/src/research/lib/merge.mjs +119 -0
- package/src/research/lib/osm.mjs +49 -0
- package/src/research/lib/report.mjs +118 -0
- package/src/research/lib/social.mjs +49 -0
- package/src/research/lib/util.mjs +104 -0
- package/src/research/lib/website.mjs +285 -0
- package/src/research/research.mjs +67 -0
- package/src/tripadvisor/README.md +78 -0
- package/src/tripadvisor/index.mjs +178 -0
- package/src/tripadvisor/links.mjs +78 -0
- package/src/tripadvisor/photos.mjs +55 -0
- package/types/index.d.mts +65 -0
- package/types/instagram/download.d.mts +1 -0
- package/types/instagram/index.d.mts +13 -0
- package/types/instagram/links.d.mts +14 -0
- package/types/instagram/record.d.mts +1 -0
- package/types/lib/edge.d.mts +14 -0
- package/types/lib/env.d.mts +12 -0
- package/types/lib/errors.d.mts +25 -0
- package/types/lib/files.d.mts +1 -0
- package/types/lib/images.d.mts +6 -0
- package/types/lib/log.d.mts +5 -0
- package/types/lib/photos.d.mts +30 -0
- package/types/lib/playwright.d.mts +1677 -0
- package/types/lib/project.d.mts +32 -0
- package/types/lib/text.d.mts +4 -0
- package/types/lib/types.d.mts +668 -0
- package/types/menu/cluvi/config.d.mts +13 -0
- package/types/menu/cluvi/extract.d.mts +2 -0
- package/types/menu/cluvi/import.d.mts +35 -0
- package/types/menu/cluvi/source.d.mts +37 -0
- package/types/menu/index.d.mts +6 -0
- package/types/menu/lib/db.d.mts +23 -0
- package/types/menu/lib/import.d.mts +11 -0
- package/types/menu/lib/menu.d.mts +24 -0
- package/types/menu/lib/run.d.mts +27 -0
- package/types/menu/raw/config.d.mts +18 -0
- package/types/menu/raw/extract.d.mts +2 -0
- package/types/menu/raw/import.d.mts +64 -0
- package/types/menu/raw/normalize.d.mts +29 -0
- package/types/menu/raw/source.d.mts +19 -0
- package/types/menu/raw/vision.d.mts +13 -0
- package/types/research/index.d.mts +9 -0
- package/types/research/lib/google.d.mts +12 -0
- package/types/research/lib/hours.d.mts +22 -0
- package/types/research/lib/merge.d.mts +87 -0
- package/types/research/lib/osm.d.mts +36 -0
- package/types/research/lib/report.d.mts +6 -0
- package/types/research/lib/social.d.mts +118 -0
- package/types/research/lib/util.d.mts +45 -0
- package/types/research/lib/website.d.mts +283 -0
- package/types/research/research.d.mts +1 -0
- package/types/tripadvisor/index.d.mts +11 -0
- package/types/tripadvisor/links.d.mts +13 -0
- package/types/tripadvisor/photos.d.mts +1 -0
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Reads and normalizes the menu: `{ menu, notes, title }`, ready for importMenu.
|
|
3
|
+
* `config` is the restaurant-specific part (see config.mjs); the default is that file's.
|
|
4
|
+
*/
|
|
5
|
+
export declare function fetchCluviMenu({ url, service, lang, config }?: {
|
|
6
|
+
config?: {
|
|
7
|
+
url: string;
|
|
8
|
+
categories: {
|
|
9
|
+
slug: string;
|
|
10
|
+
name: string;
|
|
11
|
+
from: string[];
|
|
12
|
+
}[];
|
|
13
|
+
sections: {
|
|
14
|
+
"Cócteles Autor Cannario": string;
|
|
15
|
+
Mocktails: string;
|
|
16
|
+
};
|
|
17
|
+
} | undefined;
|
|
18
|
+
}): Promise<{
|
|
19
|
+
menu: {
|
|
20
|
+
slug: any;
|
|
21
|
+
name: any;
|
|
22
|
+
sections: {
|
|
23
|
+
name: any;
|
|
24
|
+
products: any;
|
|
25
|
+
}[];
|
|
26
|
+
}[];
|
|
27
|
+
notes: string[];
|
|
28
|
+
title: string;
|
|
29
|
+
}>;
|
|
30
|
+
/**
|
|
31
|
+
* Reads the menu from Cluvi and imports it. Takes importMenu's options too.
|
|
32
|
+
* @param {import('../../lib/types.mjs').ImportCluviOptions} [options]
|
|
33
|
+
* @returns {Promise<import('../../lib/types.mjs').ImportResult>}
|
|
34
|
+
*/
|
|
35
|
+
export declare function importCluvi({ url, service, lang, config, ...importOptions }?: import('../../lib/types.mjs').ImportCluviOptions): Promise<import('../../lib/types.mjs').ImportResult>;
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/** https://<restaurant>.cluvi.co/<supplier>/maincategories gives "<supplier>". */
|
|
2
|
+
export declare function supplierSlug(menuUrl: any): string;
|
|
3
|
+
/**
|
|
4
|
+
* `service` picks which of the restaurant's menus to read. `on_table` is the
|
|
5
|
+
* digital menu guests open from the table QR code and is the complete one:
|
|
6
|
+
* `delivery` and `take_away` only list what the restaurant sells that way.
|
|
7
|
+
*/
|
|
8
|
+
export declare function fetchCluvi({ url, service, lang }: {
|
|
9
|
+
lang?: string | undefined;
|
|
10
|
+
service?: string | undefined;
|
|
11
|
+
url: any;
|
|
12
|
+
}): Promise<{
|
|
13
|
+
supplier: any;
|
|
14
|
+
raw: any;
|
|
15
|
+
service: string;
|
|
16
|
+
}>;
|
|
17
|
+
/**
|
|
18
|
+
* Cluvi's response to the shape lib/menu.mjs describes. Main categories are
|
|
19
|
+
* folded into the categories of `config.categories`, subcategories become
|
|
20
|
+
* sections, and products keep the order Cluvi shows them in (their `order`
|
|
21
|
+
* field, not their position in the subcategory's product_ids).
|
|
22
|
+
*/
|
|
23
|
+
export declare function normalizeCluvi({ supplier, raw }: {
|
|
24
|
+
raw: any;
|
|
25
|
+
supplier: any;
|
|
26
|
+
}, config: any): {
|
|
27
|
+
menu: {
|
|
28
|
+
slug: any;
|
|
29
|
+
name: any;
|
|
30
|
+
sections: {
|
|
31
|
+
name: any;
|
|
32
|
+
products: any;
|
|
33
|
+
}[];
|
|
34
|
+
}[];
|
|
35
|
+
notes: string[];
|
|
36
|
+
currency: string;
|
|
37
|
+
};
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export { importMenu } from "./lib/import.mjs";
|
|
2
|
+
export { importCluvi } from "./cluvi/import.mjs";
|
|
3
|
+
export { importImageMenu, listMenuImages } from "./raw/import.mjs";
|
|
4
|
+
export { cleanText, countMenu, sectionName, slugify, validateMenu } from "./lib/menu.mjs";
|
|
5
|
+
export { normalizePages, parsePrice } from "./raw/normalize.mjs";
|
|
6
|
+
export { defaultProvider, providers } from "./raw/vision.mjs";
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/** Opens the connection. `label` names the target without the credentials. */
|
|
2
|
+
export declare function connect(url: any, { env }?: {}): Promise<{
|
|
3
|
+
client: any;
|
|
4
|
+
label: string;
|
|
5
|
+
}>;
|
|
6
|
+
/** What an import would replace: the categories it writes, or the whole menu. */
|
|
7
|
+
export declare function inspect(client: any, menu: any, { replaceAll }?: {
|
|
8
|
+
replaceAll?: boolean | undefined;
|
|
9
|
+
}): Promise<any>;
|
|
10
|
+
/**
|
|
11
|
+
* Replaces the menu in one transaction, so readers see the old menu or the new
|
|
12
|
+
* one and a failure changes nothing. By default only the categories in `menu`
|
|
13
|
+
* are replaced (deleting a category cascades to its sections and products);
|
|
14
|
+
* `replaceAll` empties the menu first. Ids are generated here so the rows can
|
|
15
|
+
* be inserted in bulk, a column at a time.
|
|
16
|
+
*/
|
|
17
|
+
export declare function replaceMenu(client: any, menu: any, { replaceAll }?: {
|
|
18
|
+
replaceAll?: boolean | undefined;
|
|
19
|
+
}): Promise<{
|
|
20
|
+
categories: any;
|
|
21
|
+
sections: any;
|
|
22
|
+
products: any;
|
|
23
|
+
}>;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/** Things the site needs that this menu does not give it, read from the template's own files. */
|
|
2
|
+
export declare function templateHints(menu: any, { projectDir }?: {}): Promise<string[]>;
|
|
3
|
+
/**
|
|
4
|
+
* Checks `menu` (the shape of lib/menu.mjs) and writes it to the database.
|
|
5
|
+
* `notes` are what the source wants the user to know; `title` heads the log.
|
|
6
|
+
* Resolves to `{ totals, notes, written, dryRun, database }`, `database` being
|
|
7
|
+
* `{ label, current }` once it was inspected and null when it was not reached.
|
|
8
|
+
* @param {import('../../lib/types.mjs').ImportMenuOptions} options
|
|
9
|
+
* @returns {Promise<import('../../lib/types.mjs').ImportResult>}
|
|
10
|
+
*/
|
|
11
|
+
export declare function importMenu({ menu, notes, title, dryRun, json, replaceAll, force, databaseUrl, env, projectDir, log: logOption, }?: import('../../lib/types.mjs').ImportMenuOptions): Promise<import('../../lib/types.mjs').ImportResult>;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
declare const squash: (text: any) => string;
|
|
2
|
+
/** Collapses runs of whitespace (Cluvi labels carry stray spaces). */
|
|
3
|
+
export declare const cleanText: typeof squash;
|
|
4
|
+
/** Lowercase, accent-free key, to compare labels typed by different people. */
|
|
5
|
+
export declare const matchKey: (text: any) => string;
|
|
6
|
+
export declare const slugify: (text: any) => string;
|
|
7
|
+
export declare const sectionName: (text: any) => string;
|
|
8
|
+
/** Rich-text descriptions (<p>, <br>, <span style>) to plain text, one line per paragraph. */
|
|
9
|
+
export declare function htmlToText(html: any): string | null;
|
|
10
|
+
/** An invalid code would make Intl.NumberFormat throw in the site's formatPrice. */
|
|
11
|
+
export declare const isCurrency: (code: any) => boolean;
|
|
12
|
+
/**
|
|
13
|
+
* Totals of a menu.
|
|
14
|
+
* @param {import('../../lib/types.mjs').Menu} menu
|
|
15
|
+
* @returns {import('../../lib/types.mjs').MenuTotals}
|
|
16
|
+
*/
|
|
17
|
+
export declare function countMenu(menu: import('../../lib/types.mjs').Menu): import('../../lib/types.mjs').MenuTotals;
|
|
18
|
+
/**
|
|
19
|
+
* Throws a TablefactsError (EFAILED) on anything the database or the site could not take, naming the culprit.
|
|
20
|
+
* @param {import('../../lib/types.mjs').Menu} menu
|
|
21
|
+
* @returns {void}
|
|
22
|
+
*/
|
|
23
|
+
export declare function validateMenu(menu: import('../../lib/types.mjs').Menu): void;
|
|
24
|
+
export {};
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/** The option names the menu library uses in its messages, as the flags the CLI shows. */
|
|
2
|
+
export declare const menuFlags: {
|
|
3
|
+
only: string;
|
|
4
|
+
provider: string;
|
|
5
|
+
model: string;
|
|
6
|
+
minWidth: string;
|
|
7
|
+
replaceAll: string;
|
|
8
|
+
force: string;
|
|
9
|
+
dryRun: string;
|
|
10
|
+
};
|
|
11
|
+
/** A library message with option names turned into flags. */
|
|
12
|
+
export declare const flagText: (message: any) => string;
|
|
13
|
+
/**
|
|
14
|
+
* The CLI's logger: info and warn lines (progress, notes, "left untouched") go to stdout as
|
|
15
|
+
* they always did, errors to stderr, and option names in the text become flags.
|
|
16
|
+
*/
|
|
17
|
+
export declare const cliLog: (message: any, level?: string) => void;
|
|
18
|
+
/**
|
|
19
|
+
* `fetchMenu({ values, positionals })` returns `{ menu, notes, title }`: the
|
|
20
|
+
* menu in the shape of lib/menu.mjs, what the source wants the user to know,
|
|
21
|
+
* and a heading. `options` are the source's own flags, in util.parseArgs form.
|
|
22
|
+
*/
|
|
23
|
+
export declare function runImport({ usage, options, fetchMenu }: {
|
|
24
|
+
fetchMenu: any;
|
|
25
|
+
options?: {} | undefined;
|
|
26
|
+
usage: any;
|
|
27
|
+
}): Promise<void>;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
declare const _default: {
|
|
2
|
+
url: string;
|
|
3
|
+
currency: string;
|
|
4
|
+
thousands: string;
|
|
5
|
+
decimal: string;
|
|
6
|
+
scale: number;
|
|
7
|
+
categories: {
|
|
8
|
+
slug: string;
|
|
9
|
+
name: string;
|
|
10
|
+
groups: string[];
|
|
11
|
+
}[];
|
|
12
|
+
placeIn: {};
|
|
13
|
+
sections: {
|
|
14
|
+
"Cócteles de Autor": string;
|
|
15
|
+
};
|
|
16
|
+
skipSections: never[];
|
|
17
|
+
};
|
|
18
|
+
export default _default;
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/** Every image found, and the numbered ones `only` selects. `config` defaults to config.mjs. */
|
|
2
|
+
export declare function findPages({ urls, only, minWidth, config }?: {
|
|
3
|
+
config?: {
|
|
4
|
+
url: string;
|
|
5
|
+
currency: string;
|
|
6
|
+
thousands: string;
|
|
7
|
+
decimal: string;
|
|
8
|
+
scale: number;
|
|
9
|
+
categories: {
|
|
10
|
+
slug: string;
|
|
11
|
+
name: string;
|
|
12
|
+
groups: string[];
|
|
13
|
+
}[];
|
|
14
|
+
placeIn: {};
|
|
15
|
+
sections: {
|
|
16
|
+
"Cócteles de Autor": string;
|
|
17
|
+
};
|
|
18
|
+
skipSections: never[];
|
|
19
|
+
} | undefined;
|
|
20
|
+
minWidth?: number | undefined;
|
|
21
|
+
urls?: never[] | undefined;
|
|
22
|
+
}): Promise<{
|
|
23
|
+
pages: any[];
|
|
24
|
+
chosen: any[];
|
|
25
|
+
}>;
|
|
26
|
+
/**
|
|
27
|
+
* The pictures the CLI's `--list` prints, numbered. `only` narrows them.
|
|
28
|
+
* @param {import('../../lib/types.mjs').ListMenuImagesOptions} [options]
|
|
29
|
+
* @returns {Promise<import('../../lib/types.mjs').MenuImage[]>}
|
|
30
|
+
*/
|
|
31
|
+
export declare function listMenuImages(options?: import('../../lib/types.mjs').ListMenuImagesOptions): Promise<import('../../lib/types.mjs').MenuImage[]>;
|
|
32
|
+
/** Reads the pages and normalizes them: `{ menu, notes, title }`, ready for importMenu. */
|
|
33
|
+
export declare function fetchImageMenu({ urls, only, provider, model, minWidth, refresh, apiKey, env, projectDir, config, log: logOption }?: {
|
|
34
|
+
config?: {
|
|
35
|
+
url: string;
|
|
36
|
+
currency: string;
|
|
37
|
+
thousands: string;
|
|
38
|
+
decimal: string;
|
|
39
|
+
scale: number;
|
|
40
|
+
categories: {
|
|
41
|
+
slug: string;
|
|
42
|
+
name: string;
|
|
43
|
+
groups: string[];
|
|
44
|
+
}[];
|
|
45
|
+
placeIn: {};
|
|
46
|
+
sections: {
|
|
47
|
+
"Cócteles de Autor": string;
|
|
48
|
+
};
|
|
49
|
+
skipSections: never[];
|
|
50
|
+
} | undefined;
|
|
51
|
+
minWidth?: number | undefined;
|
|
52
|
+
refresh?: boolean | undefined;
|
|
53
|
+
urls?: never[] | undefined;
|
|
54
|
+
}): Promise<{
|
|
55
|
+
menu: import("../../lib/types.mjs").Menu;
|
|
56
|
+
notes: string[];
|
|
57
|
+
title: string;
|
|
58
|
+
}>;
|
|
59
|
+
/**
|
|
60
|
+
* Reads the menu from pictures with a vision model and imports it. Takes importMenu's options too.
|
|
61
|
+
* @param {import('../../lib/types.mjs').ImportImageMenuOptions} [options]
|
|
62
|
+
* @returns {Promise<import('../../lib/types.mjs').ImportResult>}
|
|
63
|
+
*/
|
|
64
|
+
export declare function importImageMenu({ urls, only, provider, model, minWidth, refresh, apiKey, env, config, ...importOptions }?: import('../../lib/types.mjs').ImportImageMenuOptions): Promise<import('../../lib/types.mjs').ImportResult>;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* "$95.000" to 95000. `thousands` and `decimal` are the separators the menu
|
|
3
|
+
* prints (Colombia: "." and ","); `scale` multiplies the result for menus that
|
|
4
|
+
* print "95" meaning 95.000. Returns null for text with no number.
|
|
5
|
+
* @param {string} text
|
|
6
|
+
* @param {import('../../lib/types.mjs').PriceFormat} [format]
|
|
7
|
+
* @returns {number | null}
|
|
8
|
+
*/
|
|
9
|
+
export declare function parsePrice(text: string, { thousands, decimal, scale }?: import('../../lib/types.mjs').PriceFormat): number | null;
|
|
10
|
+
/**
|
|
11
|
+
* `pages` is the transcription of each page, in page order. A section with no
|
|
12
|
+
* title continues the section before it (a list that runs onto the next page),
|
|
13
|
+
* and sections with the same title are merged. Each section is placed in the
|
|
14
|
+
* category of `config.categories` that lists its group (food, drink), unless
|
|
15
|
+
* `config.placeIn` names it. An item with several priced columns becomes one
|
|
16
|
+
* product per column, "Name (Botella)", because a product has one price.
|
|
17
|
+
* @param {{ number?: number, notes?: string[], sections?: any[] }[]} pages transcriptions, one per page
|
|
18
|
+
* @param {import('../../lib/types.mjs').RawConfig} config
|
|
19
|
+
* @returns {{ menu: import('../../lib/types.mjs').Menu, notes: string[], currency: string }}
|
|
20
|
+
*/
|
|
21
|
+
export declare function normalizePages(pages: {
|
|
22
|
+
number?: number;
|
|
23
|
+
notes?: string[];
|
|
24
|
+
sections?: any[];
|
|
25
|
+
}[], config: import('../../lib/types.mjs').RawConfig): {
|
|
26
|
+
menu: import('../../lib/types.mjs').Menu;
|
|
27
|
+
notes: string[];
|
|
28
|
+
currency: string;
|
|
29
|
+
};
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The picture URLs of a page, in document order. Lazy-loaders keep the real
|
|
3
|
+
* address in data-orig-src / data-src and put a placeholder in src, so those
|
|
4
|
+
* come first. Images declaring a width under `minWidth` (logos, icons) and
|
|
5
|
+
* anything that is not a JPG, PNG or WebP (SVG logos) are skipped.
|
|
6
|
+
*/
|
|
7
|
+
export declare function findImages(html: any, pageUrl: any, { minWidth }?: {
|
|
8
|
+
minWidth?: number | undefined;
|
|
9
|
+
}): any[];
|
|
10
|
+
/** Each argument is a page to scan or a direct image URL. */
|
|
11
|
+
export declare function discoverPages(inputs: any, options: any): Promise<any[]>;
|
|
12
|
+
export declare const pageId: (url: any) => string;
|
|
13
|
+
/** Downloads one page image into the cache (once) and returns where it is and what it is. */
|
|
14
|
+
export declare function downloadPage(page: any, host: any, { projectDir }?: {}): Promise<{
|
|
15
|
+
id: string;
|
|
16
|
+
dir: string;
|
|
17
|
+
file: string;
|
|
18
|
+
mediaType: string;
|
|
19
|
+
}>;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/** @type {Record<string, import('../../lib/types.mjs').VisionProvider>} */
|
|
2
|
+
export declare const providers: Record<string, import('../../lib/types.mjs').VisionProvider>;
|
|
3
|
+
export declare const defaultProvider = "anthropic";
|
|
4
|
+
/** `file` is a downloaded picture; returns `{ sections, notes }` as the schema above describes. */
|
|
5
|
+
export declare function readPage({ file, mediaType }: {
|
|
6
|
+
file: any;
|
|
7
|
+
mediaType: any;
|
|
8
|
+
}, { provider, model, apiKey, env }?: {
|
|
9
|
+
provider?: string | undefined;
|
|
10
|
+
}): Promise<{
|
|
11
|
+
sections: any;
|
|
12
|
+
notes: any;
|
|
13
|
+
}>;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Researches a restaurant from public sources and writes profile.json, report.md and
|
|
3
|
+
* setup-answers.txt. Silent unless `log` is given; a source that fails becomes a note in the
|
|
4
|
+
* report, not an error. Throws a TablefactsError with code 'EUSAGE' (and `option` 'name') when
|
|
5
|
+
* `name` is missing.
|
|
6
|
+
* @param {import('../lib/types.mjs').ResearchOptions} options
|
|
7
|
+
* @returns {Promise<import('../lib/types.mjs').ResearchResult>}
|
|
8
|
+
*/
|
|
9
|
+
export declare function research(options?: import('../lib/types.mjs').ResearchOptions): Promise<import('../lib/types.mjs').ResearchResult>;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/** Returns { place, candidates }: `place` is the first result whose name matches, or null. */
|
|
2
|
+
export declare function searchGoogle({ name, location, country, key }: {
|
|
3
|
+
country: any;
|
|
4
|
+
key: any;
|
|
5
|
+
location: any;
|
|
6
|
+
name: any;
|
|
7
|
+
}): Promise<{
|
|
8
|
+
place: any;
|
|
9
|
+
candidates: any;
|
|
10
|
+
}>;
|
|
11
|
+
/** Downloads up to `count` photos into `dir`, returns what was saved. The key stays out of the result. */
|
|
12
|
+
export declare function downloadPhotos(place: any, key: any, count: any, save: any): Promise<any[]>;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/** Google `regularOpeningHours.periods` (day 0 = Sunday). */
|
|
2
|
+
export declare function fromGoogle(periods?: any[]): {
|
|
3
|
+
week: string[][][];
|
|
4
|
+
} | null;
|
|
5
|
+
/** OpenStreetMap / schema.org `openingHours` syntax: "Mo-Th 12:00-22:00; Fr,Sa 12:00-00:00; Su off". */
|
|
6
|
+
export declare function fromOsm(text: any): {
|
|
7
|
+
week: string[][][];
|
|
8
|
+
partial?: undefined;
|
|
9
|
+
} | {
|
|
10
|
+
week: never[][];
|
|
11
|
+
partial: boolean;
|
|
12
|
+
} | null;
|
|
13
|
+
/** schema.org `openingHoursSpecification` entries. */
|
|
14
|
+
export declare function fromSpec(specs?: any[]): {
|
|
15
|
+
week: never[][];
|
|
16
|
+
} | null;
|
|
17
|
+
export declare const weekSignature: (week: any) => any;
|
|
18
|
+
/** Rows for `visit.hoursRows`: { label, value }, matching the template's wording. */
|
|
19
|
+
export declare function formatRows(week: any, lang: any): {
|
|
20
|
+
label: any;
|
|
21
|
+
value: any;
|
|
22
|
+
}[];
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
export declare function buildProfile({ query, google, osm, site, hub, instagram, tripadvisor }: {
|
|
2
|
+
google: any;
|
|
3
|
+
hub: any;
|
|
4
|
+
instagram: any;
|
|
5
|
+
osm: any;
|
|
6
|
+
query: any;
|
|
7
|
+
site: any;
|
|
8
|
+
tripadvisor: any;
|
|
9
|
+
}): {
|
|
10
|
+
query: any;
|
|
11
|
+
generatedAt: string;
|
|
12
|
+
warnings: string[];
|
|
13
|
+
fields: {
|
|
14
|
+
name: any;
|
|
15
|
+
street: any;
|
|
16
|
+
locality: any;
|
|
17
|
+
region: any;
|
|
18
|
+
country: any;
|
|
19
|
+
coordinates: any;
|
|
20
|
+
phone: any;
|
|
21
|
+
email: any;
|
|
22
|
+
instagram: any;
|
|
23
|
+
facebook: any;
|
|
24
|
+
tiktok: any;
|
|
25
|
+
tripadvisor: any;
|
|
26
|
+
website: any;
|
|
27
|
+
reserveUrl: any;
|
|
28
|
+
priceRange: any;
|
|
29
|
+
mapsUrl: any;
|
|
30
|
+
descriptor: any;
|
|
31
|
+
};
|
|
32
|
+
hours: {
|
|
33
|
+
source: string;
|
|
34
|
+
week: any;
|
|
35
|
+
rows: {
|
|
36
|
+
es: {
|
|
37
|
+
label: any;
|
|
38
|
+
value: any;
|
|
39
|
+
}[];
|
|
40
|
+
en: {
|
|
41
|
+
label: any;
|
|
42
|
+
value: any;
|
|
43
|
+
}[];
|
|
44
|
+
};
|
|
45
|
+
confidence: string;
|
|
46
|
+
conflicts: {
|
|
47
|
+
source: string;
|
|
48
|
+
rows: {
|
|
49
|
+
label: any;
|
|
50
|
+
value: any;
|
|
51
|
+
}[];
|
|
52
|
+
}[];
|
|
53
|
+
} | null;
|
|
54
|
+
textHours: any[];
|
|
55
|
+
links: {
|
|
56
|
+
menu: any[];
|
|
57
|
+
delivery: any[];
|
|
58
|
+
reserve: any[];
|
|
59
|
+
waze: any[];
|
|
60
|
+
hubs: any[];
|
|
61
|
+
};
|
|
62
|
+
ratings: any[];
|
|
63
|
+
images: {
|
|
64
|
+
logos: any[];
|
|
65
|
+
site: any;
|
|
66
|
+
hub: any;
|
|
67
|
+
googlePhotos: any;
|
|
68
|
+
instagramImage: any;
|
|
69
|
+
themeColor: any;
|
|
70
|
+
};
|
|
71
|
+
copySources: {
|
|
72
|
+
googleSummary: any;
|
|
73
|
+
siteDescription: any;
|
|
74
|
+
instagramBio: any;
|
|
75
|
+
tripadvisor: any;
|
|
76
|
+
headings: any;
|
|
77
|
+
paragraphs: any;
|
|
78
|
+
};
|
|
79
|
+
social: {
|
|
80
|
+
instagram: {
|
|
81
|
+
handle: any;
|
|
82
|
+
followers: any;
|
|
83
|
+
posts: any;
|
|
84
|
+
blocked: any;
|
|
85
|
+
} | null;
|
|
86
|
+
};
|
|
87
|
+
};
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
export declare function searchOsm({ name, location, country }: {
|
|
2
|
+
country: any;
|
|
3
|
+
location: any;
|
|
4
|
+
name: any;
|
|
5
|
+
}): Promise<{
|
|
6
|
+
place: {
|
|
7
|
+
source: string;
|
|
8
|
+
name: any;
|
|
9
|
+
street: string;
|
|
10
|
+
locality: any;
|
|
11
|
+
region: any;
|
|
12
|
+
country: any;
|
|
13
|
+
postcode: any;
|
|
14
|
+
coords: {
|
|
15
|
+
lat: number;
|
|
16
|
+
lng: number;
|
|
17
|
+
};
|
|
18
|
+
phone: any;
|
|
19
|
+
whatsapp: any;
|
|
20
|
+
email: any;
|
|
21
|
+
website: any;
|
|
22
|
+
instagram: any;
|
|
23
|
+
facebook: any;
|
|
24
|
+
cuisines: any;
|
|
25
|
+
hours: {
|
|
26
|
+
week: string[][][];
|
|
27
|
+
partial?: undefined;
|
|
28
|
+
} | {
|
|
29
|
+
week: never[][];
|
|
30
|
+
partial: boolean;
|
|
31
|
+
} | null;
|
|
32
|
+
hoursRaw: any;
|
|
33
|
+
osmUrl: string;
|
|
34
|
+
} | null;
|
|
35
|
+
candidates: any;
|
|
36
|
+
}>;
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Public Instagram profile metadata. Without a login the page only exposes the
|
|
3
|
+
* share card: "1,234 Followers, 56 Following, 789 Posts - Name (@handle) on
|
|
4
|
+
* Instagram: "bio"". The bio often carries the phone, the area and a hub link.
|
|
5
|
+
*/
|
|
6
|
+
export declare function readInstagram(handle: any): Promise<{
|
|
7
|
+
handle: any;
|
|
8
|
+
url: string;
|
|
9
|
+
blocked: any;
|
|
10
|
+
displayName?: undefined;
|
|
11
|
+
followers?: undefined;
|
|
12
|
+
posts?: undefined;
|
|
13
|
+
bio?: undefined;
|
|
14
|
+
phones?: undefined;
|
|
15
|
+
links?: undefined;
|
|
16
|
+
image?: undefined;
|
|
17
|
+
} | {
|
|
18
|
+
blocked?: undefined;
|
|
19
|
+
handle: any;
|
|
20
|
+
url: string;
|
|
21
|
+
displayName: any;
|
|
22
|
+
followers: any;
|
|
23
|
+
posts: any;
|
|
24
|
+
bio: any;
|
|
25
|
+
phones: any[];
|
|
26
|
+
links: any;
|
|
27
|
+
image: any;
|
|
28
|
+
}>;
|
|
29
|
+
/** TripAdvisor: schema.org JSON-LD when the page loads; DataDome often blocks it. */
|
|
30
|
+
export declare function readTripadvisor(url: any, { browser }?: {}): Promise<{
|
|
31
|
+
url: any;
|
|
32
|
+
blocked: string;
|
|
33
|
+
jsonld?: undefined;
|
|
34
|
+
description?: undefined;
|
|
35
|
+
hoursText?: undefined;
|
|
36
|
+
images?: undefined;
|
|
37
|
+
} | {
|
|
38
|
+
blocked?: undefined;
|
|
39
|
+
url: any;
|
|
40
|
+
jsonld: {
|
|
41
|
+
name: any;
|
|
42
|
+
telephone: any;
|
|
43
|
+
email: any;
|
|
44
|
+
priceRange: any;
|
|
45
|
+
cuisines: string[];
|
|
46
|
+
address: {
|
|
47
|
+
street: any;
|
|
48
|
+
locality: any;
|
|
49
|
+
region: any;
|
|
50
|
+
postcode: any;
|
|
51
|
+
country: any;
|
|
52
|
+
};
|
|
53
|
+
geo: {
|
|
54
|
+
lat: number;
|
|
55
|
+
lng: number;
|
|
56
|
+
} | null;
|
|
57
|
+
sameAs: string[];
|
|
58
|
+
logo: any;
|
|
59
|
+
rating: {
|
|
60
|
+
value: number;
|
|
61
|
+
count: number | null;
|
|
62
|
+
} | null;
|
|
63
|
+
hours: {
|
|
64
|
+
week: string[][][];
|
|
65
|
+
partial?: undefined;
|
|
66
|
+
} | {
|
|
67
|
+
week: never[][];
|
|
68
|
+
} | null;
|
|
69
|
+
} | null;
|
|
70
|
+
description: any;
|
|
71
|
+
hoursText: any;
|
|
72
|
+
images: any[];
|
|
73
|
+
}>;
|
|
74
|
+
/** A link-in-bio hub (Linktree, Beacons, bio.link): its links, classified like a website's. */
|
|
75
|
+
export declare function readHub(url: any, { browser }?: {}): Promise<{
|
|
76
|
+
links?: undefined;
|
|
77
|
+
images?: undefined;
|
|
78
|
+
url: any;
|
|
79
|
+
blocked: string;
|
|
80
|
+
title?: undefined;
|
|
81
|
+
meta?: undefined;
|
|
82
|
+
anchors?: undefined;
|
|
83
|
+
logos?: undefined;
|
|
84
|
+
} | {
|
|
85
|
+
blocked?: undefined;
|
|
86
|
+
url: any;
|
|
87
|
+
title: any;
|
|
88
|
+
meta: {
|
|
89
|
+
siteName: any;
|
|
90
|
+
title: any;
|
|
91
|
+
description: any;
|
|
92
|
+
themeColor: any;
|
|
93
|
+
};
|
|
94
|
+
links: {
|
|
95
|
+
tel: never[];
|
|
96
|
+
mail: never[];
|
|
97
|
+
whatsapp: never[];
|
|
98
|
+
reserve: never[];
|
|
99
|
+
menu: never[];
|
|
100
|
+
delivery: never[];
|
|
101
|
+
maps: never[];
|
|
102
|
+
waze: never[];
|
|
103
|
+
facebook: never[];
|
|
104
|
+
tiktok: never[];
|
|
105
|
+
tripadvisor: never[];
|
|
106
|
+
hubs: never[];
|
|
107
|
+
instagram: never[];
|
|
108
|
+
};
|
|
109
|
+
anchors: {
|
|
110
|
+
href: string | null;
|
|
111
|
+
text: any;
|
|
112
|
+
}[];
|
|
113
|
+
logos: {
|
|
114
|
+
url: string | null;
|
|
115
|
+
kind: any;
|
|
116
|
+
}[];
|
|
117
|
+
images: any[];
|
|
118
|
+
}>;
|