Browse Source

Enable --tmp option to specify temporary folder for downloaded tiles

Also enable resuming failed download with this option
mrkvon 8 months ago
parent
commit
fd03ac292d
10 changed files with 63 additions and 25 deletions
  1. 1
    0
      package.json
  2. 10
    8
      src/config.ts
  3. 8
    5
      src/download.ts
  4. 4
    0
      src/help.ts
  5. 2
    1
      src/map.ts
  6. 2
    1
      src/route.ts
  7. 18
    9
      src/run.ts
  8. 1
    1
      src/tile-servers.ts
  9. 9
    0
      src/utils.ts
  10. 8
    0
      yarn.lock

+ 1
- 0
package.json View File

@@ -58,6 +58,7 @@
58 58
   "dependencies": {
59 59
     "axios": "^0.19.2",
60 60
     "axios-rate-limit": "^1.3.0",
61
+    "chalk": "^4.1.2",
61 62
     "fs-extra": "^8.1.0",
62 63
     "gm": "^1.23.1",
63 64
     "haversine": "^1.1.1",

+ 10
- 8
src/config.ts View File

@@ -16,6 +16,7 @@ interface BaseConfig extends ModeConfig {
16 16
   tileServer: TileServer;
17 17
   pageSizeX: number;
18 18
   pageSizeY: number;
19
+  tmp: string;
19 20
 }
20 21
 
21 22
 interface MapConfig extends BaseConfig {
@@ -57,12 +58,13 @@ export default function getConfig(): MapConfig | RouteConfig | HelpConfig | Tile
57 58
   }
58 59
 
59 60
   if (argv.route || argv.map) {
60
-    const zoom = argv.zoom ?? 12;
61
-    const pageSizeX = argv.x ?? 4;
62
-    const pageSizeY = argv.y ?? 5;
63
-    const tileServer = getTileServer(argv['tile-server'], argv['rate-limit']);
64
-
65
-    const baseConfig = { zoom, pageSizeX, pageSizeY, tileServer };
61
+    const baseConfig = {
62
+      zoom: argv.zoom ?? 12,
63
+      pageSizeX: argv.x ?? 4,
64
+      pageSizeY: argv.y ?? 5,
65
+      tileServer: getTileServer(argv['tile-server'], argv['rate-limit']),
66
+      tmp: argv.tmp ?? `tmp${Date.now()}`,
67
+    };
66 68
 
67 69
     if (argv.route) {
68 70
       const input = argv.input;
@@ -80,7 +82,7 @@ export default function getConfig(): MapConfig | RouteConfig | HelpConfig | Tile
80 82
           `route-${input
81 83
             .split('.')
82 84
             .slice(0, -1)
83
-            .join('.')}-${zoom}`,
85
+            .join('.')}-${baseConfig.zoom}`,
84 86
       };
85 87
     }
86 88
 
@@ -98,7 +100,7 @@ export default function getConfig(): MapConfig | RouteConfig | HelpConfig | Tile
98 100
       )
99 101
         return helpConfig;
100 102
 
101
-      const output = argv.output ?? `map_${north}_${west}_${south}_${east}_${zoom}`;
103
+      const output = argv.output ?? `map_${north}_${west}_${south}_${east}_${baseConfig.zoom}`;
102 104
       return {
103 105
         ...baseConfig,
104 106
         mode: 'map',

+ 8
- 5
src/download.ts View File

@@ -3,17 +3,20 @@ import { getHttp } from './http';
3 3
 import fs from 'fs-extra';
4 4
 import mergeImg from 'merge-img';
5 5
 import log from './log';
6
-import { getFilename } from './utils';
6
+import { getFilename, fileExists } from './utils';
7 7
 
8 8
 // This is the main exported function. Provide pages, folder and server to dowload from and it fills the tmp folder with the pages
9 9
 export async function downloadPages(pages: Page[], tmp: string, tileServer: TileServer) {
10 10
   await fs.ensureDir(tmp);
11 11
   const http = getHttp(tileServer.rateLimit);
12 12
   for (let i = 0, len = pages.length; i < len; i++) {
13
-    const page = pages[i];
14
-    const info = `downloading page ${i + 1}/${pages.length}`;
15
-    const pageTiles = await getPage(page, { http, tileServer }, info);
16
-    await savePage(pageTiles, getFilename(tmp, i));
13
+    const filename = getFilename(tmp, i);
14
+    if (!(await fileExists(filename))) {
15
+      const page = pages[i];
16
+      const info = `downloading page ${i + 1}/${pages.length}`;
17
+      const pageTiles = await getPage(page, { http, tileServer }, info);
18
+      await savePage(pageTiles, filename);
19
+    }
17 20
   }
18 21
 }
19 22
 

+ 4
- 0
src/help.ts View File

@@ -14,6 +14,10 @@ osm2pdf [options]
14 14
 --output        name of the generated pdf file (".pdf" will be attached, existing files will be overwritten)
15 15
 -x              tiles per page horizontally (default 4)
16 16
 -y              tiles per page vertically (default 5)
17
+--tmp           temporary folder to save downloaded tiles to (default tmp[timestamp])
18
+                  if the folder doesn't exist, it will be created
19
+                  you can resume failed download with this option
20
+                  use carefully! folder will be deleted after successful download
17 21
 
18 22
 
19 23
 === Methods ===

+ 2
- 1
src/map.ts View File

@@ -15,6 +15,7 @@ export default async function map({
15 15
   south,
16 16
   east,
17 17
   tileServer,
18
+  tmp,
18 19
 }: {
19 20
   zoom: number;
20 21
   output: string;
@@ -25,11 +26,11 @@ export default async function map({
25 26
   south: number;
26 27
   east: number;
27 28
   tileServer: TileServer;
29
+  tmp: string;
28 30
 }) {
29 31
   // collect pages
30 32
   const pages: Page[] = boundaries2pages({ north, west, south, east, pageSizeX, pageSizeY, zoom });
31 33
   // download pages
32
-  const tmp = `tmp${Date.now()}`;
33 34
   await downloadPages(pages, tmp, tileServer);
34 35
   // create pdf
35 36
   await createPdf(output, tmp);

+ 2
- 1
src/route.ts View File

@@ -36,6 +36,7 @@ export default async function path({
36 36
   distance,
37 37
   distanceStep,
38 38
   tileServer,
39
+  tmp,
39 40
 }: {
40 41
   zoom: number;
41 42
   input: string;
@@ -46,6 +47,7 @@ export default async function path({
46 47
   distance: boolean;
47 48
   distanceStep: number;
48 49
   tileServer: TileServer;
50
+  tmp: string;
49 51
 }) {
50 52
   // collect pages:
51 53
   //
@@ -59,7 +61,6 @@ export default async function path({
59 61
   const pages = collectPages(tileRoute, pageSizeX, pageSizeY);
60 62
 
61 63
   // download the tiles and connect them to pages
62
-  const tmp = `tmp${Date.now()}`;
63 64
   await downloadPages(pages, tmp, tileServer);
64 65
 
65 66
   // draw path on pages

+ 18
- 9
src/run.ts View File

@@ -13,32 +13,41 @@ import map from './map';
13 13
 import route from './route';
14 14
 import help from './help';
15 15
 import { listTileServers } from './tile-servers';
16
+import chalk from 'chalk';
16 17
 
17 18
 (async () => {
19
+  let config;
18 20
   try {
19
-    const config = getConfig();
21
+    config = getConfig();
20 22
 
21 23
     switch (config.mode) {
22 24
       case 'tiles': {
23
-        return listTileServers();
25
+        listTileServers();
26
+        return;
24 27
       }
25 28
       case 'map': {
26
-        const { zoom, output, pageSizeX, pageSizeY, north, west, south, east, tileServer } = config;
27
-        return map({ zoom, output, pageSizeX, pageSizeY, north, west, south, east, tileServer });
29
+        await map(config);
30
+        return;
28 31
       }
29 32
       case 'route': {
30
-        const { zoom, input, output, pageSizeX, pageSizeY, draw, distance, distanceStep, tileServer } = config;
31
-        return route({ zoom, input, output, pageSizeX, pageSizeY, draw, distance, distanceStep, tileServer });
33
+        await route(config);
34
+        return;
32 35
       }
33 36
       default:
34
-        return help();
37
+        help();
38
+        return;
35 39
     }
36 40
   } catch (e) {
37
-    // tslint:disable-next-line:no-console
38
-    console.log(JSON.stringify(e));
39 41
     // tslint:disable-next-line:no-console
40 42
     console.log(JSON.stringify(e));
41 43
     // tslint:disable-next-line:no-console
42 44
     console.error(e);
45
+    if (config && 'tmp' in config) {
46
+      console.log(
47
+        chalk.red(
48
+          `\n\n************************\n\nError: ${e.message}\n\nYour download failed. You can resume it by adding "--tmp ${config.tmp}" to your command.\n\n************************\n`,
49
+        ),
50
+      );
51
+    }
43 52
   }
44 53
 })();

+ 1
- 1
src/tile-servers.ts View File

@@ -37,7 +37,7 @@ export const rawServers = [
37 37
   {
38 38
     name: 'OpenTopoMap',
39 39
     url: 'https://{a|b|c}.tile.opentopomap.org/{z}/{x}/{y}.png',
40
-    rateLimit: 1,
40
+    rateLimit: 2,
41 41
   },
42 42
   {
43 43
     name: 'Stamen Toner Black & White map',

+ 9
- 0
src/utils.ts View File

@@ -13,3 +13,12 @@ export const getFilename = (tmp: string, i: number) => `${tmp}/${pad(i)}.png`;
13 13
 export function random<T>(input: Array<T>): T {
14 14
   return input[Math.floor(Math.random() * input.length)];
15 15
 }
16
+
17
+export const fileExists = async (file: string): Promise<boolean> => {
18
+  try {
19
+    await fs.access(file, fs.constants.F_OK);
20
+    return true;
21
+  } catch {
22
+    return false;
23
+  }
24
+};

+ 8
- 0
yarn.lock View File

@@ -861,6 +861,14 @@ chalk@^3.0.0:
861 861
     ansi-styles "^4.1.0"
862 862
     supports-color "^7.1.0"
863 863
 
864
+chalk@^4.1.2:
865
+  version "4.1.2"
866
+  resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01"
867
+  integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==
868
+  dependencies:
869
+    ansi-styles "^4.1.0"
870
+    supports-color "^7.1.0"
871
+
864 872
 ci-info@^2.0.0:
865 873
   version "2.0.0"
866 874
   resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-2.0.0.tgz#67a9e964be31a51e15e5010d58e6f12834002f46"