mirror of
https://github.com/Cyclenerd/offline-map-tile-downloader.git
synced 2026-07-13 13:21:28 +02:00
Compare commits
40 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| c91d609a17 | |||
| 82fdb3c803 | |||
| a9ab9c80cd | |||
| ded4de2ed0 | |||
| aa4a4bc188 | |||
| 128675600b | |||
| 4d19139a6a | |||
| 309f892d42 | |||
| 28425a2e3a | |||
| b9b139112d | |||
| cd490f7643 | |||
| 00921d4559 | |||
| 6710302eb6 | |||
| 43c03e2f19 | |||
| af99a2fb60 | |||
| 936bf423f0 | |||
| 57693200d3 | |||
| 6da09b9b14 | |||
| ea126cd19e | |||
| bf82363e07 | |||
| 4f754129e9 | |||
| c7ae6cbcc7 | |||
| 7430f206ef | |||
| aef607d2cd | |||
| 6e2d7805d9 | |||
| b62f361d12 | |||
| 57c4327b0a | |||
| 0ac818f61d | |||
| bbc0203a4e | |||
| a89fc917ad | |||
| 993228788c | |||
| 9e59178352 | |||
| bd7421719d | |||
| 3b8e4b7fd5 | |||
| 0284d1f611 | |||
| fcb149ff4c | |||
| adbabfb39e | |||
| 3eb4c2f56f | |||
| c444287468 | |||
| b4e7912f58 |
@@ -12,11 +12,11 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: 🛎️ Checkout
|
- name: 🛎️ Checkout
|
||||||
uses: actions/checkout@v5
|
uses: actions/checkout@v7
|
||||||
|
|
||||||
# https://github.com/marketplace/actions/setup-go-environment
|
# https://github.com/marketplace/actions/setup-go-environment
|
||||||
- name: 🔧 Setup go
|
- name: 🔧 Setup go
|
||||||
uses: actions/setup-go@v5
|
uses: actions/setup-go@v6
|
||||||
|
|
||||||
- name: 🧝♀️ Check formatting
|
- name: 🧝♀️ Check formatting
|
||||||
run: |
|
run: |
|
||||||
@@ -28,7 +28,7 @@ jobs:
|
|||||||
|
|
||||||
# https://github.com/marketplace/actions/run-golangci-lint
|
# https://github.com/marketplace/actions/run-golangci-lint
|
||||||
- name: 🌡️ Lint
|
- name: 🌡️ Lint
|
||||||
uses: golangci/golangci-lint-action@v8
|
uses: golangci/golangci-lint-action@v9
|
||||||
|
|
||||||
- name: 🍳 Build
|
- name: 🍳 Build
|
||||||
run: make native
|
run: make native
|
||||||
|
|||||||
@@ -11,11 +11,11 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
|
|
||||||
- name: 🛎️ Checkout
|
- name: 🛎️ Checkout
|
||||||
uses: actions/checkout@v5
|
uses: actions/checkout@v7
|
||||||
|
|
||||||
# https://github.com/marketplace/actions/setup-go-environment
|
# https://github.com/marketplace/actions/setup-go-environment
|
||||||
- name: 🔧 Setup go
|
- name: 🔧 Setup go
|
||||||
uses: actions/setup-go@v5
|
uses: actions/setup-go@v6
|
||||||
|
|
||||||
- name: 🍳 Build
|
- name: 🍳 Build
|
||||||
run: make
|
run: make
|
||||||
@@ -26,7 +26,7 @@ jobs:
|
|||||||
# Upload binaries
|
# Upload binaries
|
||||||
# https://github.com/marketplace/actions/upload-a-build-artifact
|
# https://github.com/marketplace/actions/upload-a-build-artifact
|
||||||
- name: 📤 Upload
|
- name: 📤 Upload
|
||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v7
|
||||||
with:
|
with:
|
||||||
name: offline-map-tile-downloader-artifact
|
name: offline-map-tile-downloader-artifact
|
||||||
path: offline-map-tile-downloader-*
|
path: offline-map-tile-downloader-*
|
||||||
@@ -40,7 +40,7 @@ jobs:
|
|||||||
# Download binaries
|
# Download binaries
|
||||||
# https://github.com/marketplace/actions/download-a-build-artifact
|
# https://github.com/marketplace/actions/download-a-build-artifact
|
||||||
- name: 📥 Download
|
- name: 📥 Download
|
||||||
uses: actions/download-artifact@v5
|
uses: actions/download-artifact@v8
|
||||||
with:
|
with:
|
||||||
name: offline-map-tile-downloader-artifact
|
name: offline-map-tile-downloader-artifact
|
||||||
- name: 🌡️ Test
|
- name: 🌡️ Test
|
||||||
@@ -52,7 +52,7 @@ jobs:
|
|||||||
runs-on: macos-latest
|
runs-on: macos-latest
|
||||||
steps:
|
steps:
|
||||||
- name: 📥 Download
|
- name: 📥 Download
|
||||||
uses: actions/download-artifact@v5
|
uses: actions/download-artifact@v8
|
||||||
with:
|
with:
|
||||||
name: offline-map-tile-downloader-artifact
|
name: offline-map-tile-downloader-artifact
|
||||||
- name: 🌡️ Test
|
- name: 🌡️ Test
|
||||||
@@ -64,7 +64,7 @@ jobs:
|
|||||||
runs-on: windows-latest
|
runs-on: windows-latest
|
||||||
steps:
|
steps:
|
||||||
- name: 📥 Download
|
- name: 📥 Download
|
||||||
uses: actions/download-artifact@v5
|
uses: actions/download-artifact@v8
|
||||||
with:
|
with:
|
||||||
name: offline-map-tile-downloader-artifact
|
name: offline-map-tile-downloader-artifact
|
||||||
- name: 🌡️ Test
|
- name: 🌡️ Test
|
||||||
|
|||||||
@@ -13,11 +13,11 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
|
|
||||||
- name: 🛎️ Checkout
|
- name: 🛎️ Checkout
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v7
|
||||||
|
|
||||||
# https://github.com/marketplace/actions/setup-go-environment
|
# https://github.com/marketplace/actions/setup-go-environment
|
||||||
- name: 🔧 Setup go
|
- name: 🔧 Setup go
|
||||||
uses: actions/setup-go@v5
|
uses: actions/setup-go@v6
|
||||||
|
|
||||||
- name: 🍳 Build
|
- name: 🍳 Build
|
||||||
run: make
|
run: make
|
||||||
@@ -28,7 +28,7 @@ jobs:
|
|||||||
# Upload binaries
|
# Upload binaries
|
||||||
# https://github.com/marketplace/actions/upload-a-build-artifact
|
# https://github.com/marketplace/actions/upload-a-build-artifact
|
||||||
- name: 📤 Upload
|
- name: 📤 Upload
|
||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v7
|
||||||
with:
|
with:
|
||||||
name: offline-map-tile-downloader-artifact
|
name: offline-map-tile-downloader-artifact
|
||||||
path: offline-map-tile-downloader-*
|
path: offline-map-tile-downloader-*
|
||||||
@@ -42,7 +42,7 @@ jobs:
|
|||||||
# Download binaries
|
# Download binaries
|
||||||
# https://github.com/marketplace/actions/download-a-build-artifact
|
# https://github.com/marketplace/actions/download-a-build-artifact
|
||||||
- name: 📥 Download
|
- name: 📥 Download
|
||||||
uses: actions/download-artifact@v4
|
uses: actions/download-artifact@v8
|
||||||
with:
|
with:
|
||||||
name: offline-map-tile-downloader-artifact
|
name: offline-map-tile-downloader-artifact
|
||||||
- name: 🌡️ Test
|
- name: 🌡️ Test
|
||||||
@@ -54,7 +54,7 @@ jobs:
|
|||||||
runs-on: macos-latest
|
runs-on: macos-latest
|
||||||
steps:
|
steps:
|
||||||
- name: 📥 Download
|
- name: 📥 Download
|
||||||
uses: actions/download-artifact@v4
|
uses: actions/download-artifact@v8
|
||||||
with:
|
with:
|
||||||
name: offline-map-tile-downloader-artifact
|
name: offline-map-tile-downloader-artifact
|
||||||
- name: 🌡️ Test
|
- name: 🌡️ Test
|
||||||
@@ -66,7 +66,7 @@ jobs:
|
|||||||
runs-on: windows-latest
|
runs-on: windows-latest
|
||||||
steps:
|
steps:
|
||||||
- name: 📥 Download
|
- name: 📥 Download
|
||||||
uses: actions/download-artifact@v4
|
uses: actions/download-artifact@v8
|
||||||
with:
|
with:
|
||||||
name: offline-map-tile-downloader-artifact
|
name: offline-map-tile-downloader-artifact
|
||||||
- name: 🌡️ Test
|
- name: 🌡️ Test
|
||||||
@@ -79,13 +79,13 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
# Download all artifacts to the current working directory
|
# Download all artifacts to the current working directory
|
||||||
- name: 📥 Download gcosts
|
- name: 📥 Download gcosts
|
||||||
uses: actions/download-artifact@v4
|
uses: actions/download-artifact@v8
|
||||||
with:
|
with:
|
||||||
name: offline-map-tile-downloader-artifact
|
name: offline-map-tile-downloader-artifact
|
||||||
# Release, upload files
|
# Release, upload files
|
||||||
# https://github.com/softprops/action-gh-release
|
# https://github.com/softprops/action-gh-release
|
||||||
- name: ✨ Release
|
- name: ✨ Release
|
||||||
uses: softprops/action-gh-release@v2.2.2
|
uses: softprops/action-gh-release@v3.0.1
|
||||||
with:
|
with:
|
||||||
files: |
|
files: |
|
||||||
offline-map-tile-downloader-linux-x86_64
|
offline-map-tile-downloader-linux-x86_64
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
[](#readme)
|
[](#readme)
|
||||||
[](#readme)
|
[](#readme)
|
||||||
|
|
||||||
**Create your own offline maps for any location on Earth!** This tool allows you to download map tiles from various sources and use them in your offline applications, with a special focus on the needs of the **Off-Grid** and **Meshtastic** communities.
|
**Create your own offline maps for any location on Earth!** This tool allows you to download map tiles from various sources and use them in your offline applications, with a special focus on the needs of the **Off-Grid**, **Meshtastic** and **MeshCore** communities.
|
||||||
|
|
||||||
| Download | Offline Mode |
|
| Download | Offline Mode |
|
||||||
|----------|--------------|
|
|----------|--------------|
|
||||||
@@ -19,7 +19,7 @@ Whether you're a hiker, prepper, sailor, or just someone who wants to be prepare
|
|||||||
In a world that's increasingly reliant on internet connectivity, being able to access information offline is a superpower. This is especially true for:
|
In a world that's increasingly reliant on internet connectivity, being able to access information offline is a superpower. This is especially true for:
|
||||||
|
|
||||||
* **The Off-Grid Community:** When you're living off the grid, you can't rely on a stable internet connection. This tool allows you to have detailed maps of your surroundings, which is essential for navigation, resource management, and safety.
|
* **The Off-Grid Community:** When you're living off the grid, you can't rely on a stable internet connection. This tool allows you to have detailed maps of your surroundings, which is essential for navigation, resource management, and safety.
|
||||||
* **The Meshtastic Community:** Meshtastic is a fantastic open-source, off-grid, decentralized, mesh networking project. It allows you to send messages and other data over long distances without needing the internet. This tool allows you to create custom map tiles that can be used with the Meshtastic UI, giving you a visual representation of your mesh network on a map, even when you're completely offline.
|
* **The Meshtastic and MeshCore Community:** This tool allows you to create custom map tiles that can be used with the Meshtastic UI or MeshCore Ripple Firmware, giving you a visual representation of your mesh network on a map, even when you're completely offline.
|
||||||
|
|
||||||
## Features
|
## Features
|
||||||
|
|
||||||
@@ -28,7 +28,7 @@ In a world that's increasingly reliant on internet connectivity, being able to a
|
|||||||
* **Concurrent Downloads:** Downloads multiple tiles concurrently for faster performance.
|
* **Concurrent Downloads:** Downloads multiple tiles concurrently for faster performance.
|
||||||
* **Rate Limiting:** Limits the number of tile downloads per second to avoid overloading the tile server.
|
* **Rate Limiting:** Limits the number of tile downloads per second to avoid overloading the tile server.
|
||||||
* **Cancellable Downloads:** Cancel ongoing downloads at any time.
|
* **Cancellable Downloads:** Cancel ongoing downloads at any time.
|
||||||
* **8-bit PNG Conversion:** Option to convert downloaded tiles to 8-bit PNGs, ideal for devices with limited color palettes like the Meshtastic UI.
|
* **8-bit PNG Conversion:** Option to convert downloaded tiles to 8-bit PNGs, ideal for devices with limited color palettes like the Meshtastic UI and Ripple Firmware.
|
||||||
* **Offline Tile Server:** Serve downloaded tiles directly from the application, allowing you to use them in offline map applications.
|
* **Offline Tile Server:** Serve downloaded tiles directly from the application, allowing you to use them in offline map applications.
|
||||||
* **Cross-platform:** Works on Windows, macOS, and Linux.
|
* **Cross-platform:** Works on Windows, macOS, and Linux.
|
||||||
|
|
||||||
@@ -50,7 +50,7 @@ Don't worry, it's easier than it looks!
|
|||||||
1. Press the <kbd>Windows key</kbd> + <kbd>X</kbd>.
|
1. Press the <kbd>Windows key</kbd> + <kbd>X</kbd>.
|
||||||
1. Choose "Windows PowerShell".
|
1. Choose "Windows PowerShell".
|
||||||
1. Type `cd` followed by the path to your your folder where you saved the application (e.g., `cd C:\Users\YourName\Documents\OfflineMaps`) and press Enter.
|
1. Type `cd` followed by the path to your your folder where you saved the application (e.g., `cd C:\Users\YourName\Documents\OfflineMaps`) and press Enter.
|
||||||
1. Type `offline-map-tile-downloader.exe` and press Enter.
|
1. Type `.\offline-map-tile-downloader.exe` and press Enter.
|
||||||
1. Open your web browser and go to [`http://localhost:8080`](http://localhost:8080).
|
1. Open your web browser and go to [`http://localhost:8080`](http://localhost:8080).
|
||||||
|
|
||||||
### <img src="https://developer.apple.com/favicon.ico" width=16 height=16/> macOS (Terminal)
|
### <img src="https://developer.apple.com/favicon.ico" width=16 height=16/> macOS (Terminal)
|
||||||
@@ -105,6 +105,18 @@ If you're a developer or want to modify the code, you can build the application
|
|||||||
4. **Open your web browser** and go to `http://localhost:8080`.
|
4. **Open your web browser** and go to `http://localhost:8080`.
|
||||||
|
|
||||||
|
|
||||||
|
## Responsible Usage
|
||||||
|
|
||||||
|
**Please use this tool responsibly!** When downloading map tiles:
|
||||||
|
|
||||||
|
* **Respect tile server limits:** Use reasonable rate limits to avoid overloading map tile servers. The default rate limit is 10 tiles per second, which is conservative for most servers.
|
||||||
|
* **Avoid excessive downloads:** Only download the areas and zoom levels you actually need. Downloading entire continents at high zoom levels can generate millions of tiles.
|
||||||
|
* **Check terms of service:** Review the terms of service of the map tile provider you're using. Some providers have specific restrictions on bulk downloading.
|
||||||
|
* **Risk of being banned:** Aggressive downloading patterns can result in your IP address being temporarily or permanently banned from tile servers.
|
||||||
|
* **Consider self-hosting:** For large-scale or repeated downloads, consider setting up your own tile server.
|
||||||
|
|
||||||
|
The default settings are designed to be respectful of tile servers, but you can adjust them based on your specific needs and the tile provider's policies.
|
||||||
|
|
||||||
## File Storage
|
## File Storage
|
||||||
|
|
||||||
The downloaded map tiles are stored in the local filesystem. The default directory is `maps`, but you can change this using the `-maps-directory` command-line option. The tiles are organized by map style, zoom level, and tile coordinates.
|
The downloaded map tiles are stored in the local filesystem. The default directory is `maps`, but you can change this using the `-maps-directory` command-line option. The tiles are organized by map style, zoom level, and tile coordinates.
|
||||||
@@ -115,18 +127,36 @@ You can also use command-line options to configure the application:
|
|||||||
|
|
||||||
* `-port`: The port number for the server (default: `8080`).
|
* `-port`: The port number for the server (default: `8080`).
|
||||||
* `-maps-directory`: The directory for cached map tiles (default: `maps`).
|
* `-maps-directory`: The directory for cached map tiles (default: `maps`).
|
||||||
* `-max-workers`: The number of concurrent download workers (default: `10`).
|
* `-max-workers`: The number of concurrent download workers (default: `4`, max: `10`). Lower values are more respectful to tile servers.
|
||||||
* `-rate-limit`: The maximum number of tiles to download per second (default: `50`).
|
* `-rate-limit`: The maximum number of tiles to download per second (default: `10`, max: `50`). Keep this low to avoid being blocked.
|
||||||
* `-max-retries`: The maximum number of retries for downloading a tile (default: `3`).
|
* `-max-retries`: The maximum number of retries for downloading a tile (default: `3`).
|
||||||
|
* `-user-agent`: User-Agent header for HTTP requests (default: `mesh/YYMMDD (OS)` where date changes daily).
|
||||||
* `-help`: Show the help message.
|
* `-help`: Show the help message.
|
||||||
|
|
||||||
|
**Being respectful to tile servers:**
|
||||||
|
- Uses conservative default rate limits (10 tiles/sec, 4 workers)
|
||||||
|
- Adds random delays (100-300ms) between requests to avoid hammering servers
|
||||||
|
- Identifies itself honestly as a tile downloader
|
||||||
|
- Respects retry limits with exponential backoff
|
||||||
|
|
||||||
|
**To reduce load further (recommended):**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./offline-map-tile-downloader -max-workers 2 -rate-limit 5
|
||||||
|
```
|
||||||
|
|
||||||
|
**Important:** Always respect the tile server's Terms of Service and usage policies. Many servers have usage limits. Consider:
|
||||||
|
- Using lower rate limits for large downloads
|
||||||
|
- Downloading during off-peak hours
|
||||||
|
- Setting up your own tile server for heavy usage
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
./offline-map-tile-downloader -port 8081 -maps-directory my-tile-cache -max-workers 5 -rate-limit 25
|
./offline-map-tile-downloader -port 8081 -maps-directory my-tile-cache -max-workers 2 -rate-limit 5
|
||||||
```
|
```
|
||||||
|
|
||||||
## Meshtastic Integration
|
## Meshtastic UI Integration
|
||||||
|
|
||||||
This tool is perfect for creating offline maps for the Meshtastic UI. Here's how to do it:
|
This tool is perfect for creating offline maps for the Meshtastic UI. Here's how to do it:
|
||||||
|
|
||||||
@@ -138,6 +168,19 @@ This tool is perfect for creating offline maps for the Meshtastic UI. Here's how
|
|||||||
2. **Use with Meshtastic:**
|
2. **Use with Meshtastic:**
|
||||||
* The downloaded tiles are stored in the `maps` directory. You can now use these tiles with the Meshtastic UI. For more information on how to do this, please refer to the [Meshtastic documentation](https://meshtastic.org/docs/software/meshtastic-ui/#map).
|
* The downloaded tiles are stored in the `maps` directory. You can now use these tiles with the Meshtastic UI. For more information on how to do this, please refer to the [Meshtastic documentation](https://meshtastic.org/docs/software/meshtastic-ui/#map).
|
||||||
|
|
||||||
|
## MeshCore Ripple and MeshOS Firmware Integration
|
||||||
|
|
||||||
|
This tool is perfect for creating offline maps for the MeshCore Ripple and MeshOS Firmware.
|
||||||
|
Here's how to do it:
|
||||||
|
|
||||||
|
1. **Download the tiles:**
|
||||||
|
* Select the area you want to download.
|
||||||
|
* **Check the "Convert to 8-bit" checkbox.** This is recommended for the Ripple and MeshOS firmware to save storage space.
|
||||||
|
* Click "Download Tiles".
|
||||||
|
|
||||||
|
2. **Use with Ripple Firmware:**
|
||||||
|
* The downloaded tiles are stored in the `maps` directory. You can now use these tiles with the Ripple and MeshOS firmware. Copy the subfolder named after the selected map style to an SD card and rename it `tiles`. For more information on how to do this, please refer to the [MeshRipple Firmware documentation](https://buymeacoffee.com/ripplebiz/ultra-v7-7-guide-meshcore-users).
|
||||||
|
|
||||||
## Configuration
|
## Configuration
|
||||||
|
|
||||||
You can add your own map sources by editing the [`config/map_sources.json`](./config/map_sources.json) file. The format is simple:
|
You can add your own map sources by editing the [`config/map_sources.json`](./config/map_sources.json) file. The format is simple:
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"regexp"
|
"regexp"
|
||||||
|
"runtime"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
@@ -54,8 +55,29 @@ var (
|
|||||||
maxWorkers *int
|
maxWorkers *int
|
||||||
rateLimit *int
|
rateLimit *int
|
||||||
maxRetries *int
|
maxRetries *int
|
||||||
|
userAgent *string
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// generateUserAgent returns a basic user agent that identifies as a tile downloader
|
||||||
|
func generateUserAgent() string {
|
||||||
|
osName := runtime.GOOS
|
||||||
|
var osInfo string
|
||||||
|
|
||||||
|
switch osName {
|
||||||
|
case "darwin":
|
||||||
|
osInfo = "Macintosh"
|
||||||
|
case "linux":
|
||||||
|
osInfo = "Linux"
|
||||||
|
case "windows":
|
||||||
|
osInfo = "Windows"
|
||||||
|
default:
|
||||||
|
osInfo = osName
|
||||||
|
}
|
||||||
|
|
||||||
|
version := time.Now().Format("060102")
|
||||||
|
return fmt.Sprintf("mesh/%s (%s)", version, osInfo)
|
||||||
|
}
|
||||||
|
|
||||||
// Tile represents a single map tile with X, Y coordinates and zoom level Z.
|
// Tile represents a single map tile with X, Y coordinates and zoom level Z.
|
||||||
type Tile struct {
|
type Tile struct {
|
||||||
X, Y, Z uint32
|
X, Y, Z uint32
|
||||||
@@ -98,9 +120,10 @@ func main() {
|
|||||||
// Command line flags
|
// Command line flags
|
||||||
port := flag.Int("port", 8080, "Port number for the server")
|
port := flag.Int("port", 8080, "Port number for the server")
|
||||||
cacheDir = flag.String("maps-directory", "maps", "Directory for storing map tiles. This is where the downloaded tiles will be saved.")
|
cacheDir = flag.String("maps-directory", "maps", "Directory for storing map tiles. This is where the downloaded tiles will be saved.")
|
||||||
maxWorkers = flag.Int("max-workers", 10, "Number of concurrent download workers")
|
maxWorkers = flag.Int("max-workers", 4, "Number of concurrent download workers (max: 10)")
|
||||||
rateLimit = flag.Int("rate-limit", 50, "Maximum number of tiles to download per second")
|
rateLimit = flag.Int("rate-limit", 10, "Maximum number of tiles to download per second (max: 50)")
|
||||||
maxRetries = flag.Int("max-retries", 3, "Maximum number of retries for downloading a tile")
|
maxRetries = flag.Int("max-retries", 3, "Maximum number of retries for downloading a tile")
|
||||||
|
userAgent = flag.String("user-agent", generateUserAgent(), "User-Agent header for HTTP requests")
|
||||||
help := flag.Bool("help", false, "Show help message")
|
help := flag.Bool("help", false, "Show help message")
|
||||||
|
|
||||||
flag.Parse()
|
flag.Parse()
|
||||||
@@ -110,6 +133,14 @@ func main() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if *maxWorkers > 10 {
|
||||||
|
log.Fatalf("max-workers cannot exceed 10 (got %d)", *maxWorkers)
|
||||||
|
}
|
||||||
|
|
||||||
|
if *rateLimit > 50 {
|
||||||
|
log.Fatalf("rate-limit cannot exceed 50 (got %d)", *rateLimit)
|
||||||
|
}
|
||||||
|
|
||||||
// Create cache directory if it doesn't exist.
|
// Create cache directory if it doesn't exist.
|
||||||
if err := os.MkdirAll(*cacheDir, 0755); err != nil {
|
if err := os.MkdirAll(*cacheDir, 0755); err != nil {
|
||||||
log.Fatalf("Failed to create cache directory: %v", err)
|
log.Fatalf("Failed to create cache directory: %v", err)
|
||||||
@@ -426,7 +457,13 @@ func downloadTile(ctx context.Context, msgChan chan<- WSMessage, tile Tile, mapS
|
|||||||
time.Sleep(time.Second * time.Duration(math.Pow(2, float64(attempt))))
|
time.Sleep(time.Second * time.Duration(math.Pow(2, float64(attempt))))
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
req.Header.Set("User-Agent", "MapTileDownloader/1.0 (Go)")
|
|
||||||
|
// Set basic headers
|
||||||
|
req.Header.Set("User-Agent", *userAgent)
|
||||||
|
req.Header.Set("Accept", "image/*")
|
||||||
|
|
||||||
|
// Add small random delay between requests (100-300ms)
|
||||||
|
time.Sleep(time.Millisecond * time.Duration(100+rand.Intn(200)))
|
||||||
|
|
||||||
resp, err := http.DefaultClient.Do(req)
|
resp, err := http.DefaultClient.Do(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
+31
-14
@@ -34,7 +34,7 @@
|
|||||||
}
|
}
|
||||||
#progress {
|
#progress {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 200px;
|
top: 250px;
|
||||||
right: 11px;
|
right: 11px;
|
||||||
z-index: 1000;
|
z-index: 1000;
|
||||||
background: rgba(241, 242, 243, 0.736);
|
background: rgba(241, 242, 243, 0.736);
|
||||||
@@ -48,6 +48,11 @@
|
|||||||
<div style="position: relative;">
|
<div style="position: relative;">
|
||||||
<div id="map"></div>
|
<div id="map"></div>
|
||||||
<div class="form-container">
|
<div class="form-container">
|
||||||
|
<div style="margin-bottom: 10px; padding-bottom: 10px; border-bottom: 1px solid #ccc;">
|
||||||
|
<label for="coord_search">Go to Coordinates:</label><br>
|
||||||
|
<input type="text" id="coord_search" placeholder="lat, lng (e.g. 53.55, 10)" style="width: 200px;">
|
||||||
|
<button type="button" id="goToBtn">Go</button>
|
||||||
|
</div>
|
||||||
<form id="downloadForm">
|
<form id="downloadForm">
|
||||||
<label for="map_style">Map Style:</label>
|
<label for="map_style">Map Style:</label>
|
||||||
<select id="map_style" name="map_style"></select><br>
|
<select id="map_style" name="map_style"></select><br>
|
||||||
@@ -84,23 +89,35 @@
|
|||||||
console.error("WebSocket error:", error);
|
console.error("WebSocket error:", error);
|
||||||
};
|
};
|
||||||
|
|
||||||
var map = L.map('map');
|
var map = L.map('map').setView([53.55, 10], 13);
|
||||||
var tileLayer = L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
|
var tileLayer = L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
|
||||||
attribution: '© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors',
|
attribution: '© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors',
|
||||||
maxZoom: 19
|
maxZoom: 19
|
||||||
}).addTo(map);
|
}).addTo(map);
|
||||||
|
|
||||||
if (navigator.geolocation) {
|
// Coordinate search functionality
|
||||||
navigator.geolocation.getCurrentPosition(function(position) {
|
document.getElementById('goToBtn').addEventListener('click', function() {
|
||||||
var lat = position.coords.latitude;
|
var input = document.getElementById('coord_search').value.trim();
|
||||||
var lng = position.coords.longitude;
|
var parts = input.split(',');
|
||||||
map.setView([lat, lng], 13);
|
if (parts.length === 2) {
|
||||||
}, function() {
|
var lat = parseFloat(parts[0].trim());
|
||||||
map.setView([53.55, 10], 11);
|
var lng = parseFloat(parts[1].trim());
|
||||||
});
|
if (!isNaN(lat) && !isNaN(lng) && lat >= -90 && lat <= 90 && lng >= -180 && lng <= 180) {
|
||||||
} else {
|
map.setView([lat, lng], 13);
|
||||||
map.setView([53.55, 10], 11);
|
} else {
|
||||||
}
|
alert('Invalid coordinates. Latitude must be -90 to 90, longitude must be -180 to 180.');
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
alert('Please enter coordinates in format: lat, lng');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
document.getElementById('coord_search').addEventListener('keypress', function(e) {
|
||||||
|
if (e.key === 'Enter') {
|
||||||
|
e.preventDefault();
|
||||||
|
document.getElementById('goToBtn').click();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
var drawnItems = new L.FeatureGroup();
|
var drawnItems = new L.FeatureGroup();
|
||||||
map.addLayer(drawnItems);
|
map.addLayer(drawnItems);
|
||||||
@@ -343,4 +360,4 @@
|
|||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
Reference in New Issue
Block a user