location-tracker 1.0.0__tar.gz

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.
@@ -0,0 +1,29 @@
1
+ ---
2
+ name: Bug Report
3
+ about: Something isn't working as expected
4
+ title: ''
5
+ labels: bug
6
+ assignees: ''
7
+ ---
8
+
9
+ **Describe the bug**
10
+ A clear description of what's wrong.
11
+
12
+ **To reproduce**
13
+ 1. Run `location-tracker ...`
14
+ 2. Open dashboard at ...
15
+ 3. Click on ...
16
+ 4. See error
17
+
18
+ **Expected behavior**
19
+ What should happen instead.
20
+
21
+ **Environment**
22
+ - OS: [e.g. macOS 15.1]
23
+ - Python: [e.g. 3.13]
24
+ - Browser: [e.g. Chrome 130]
25
+
26
+ **Logs**
27
+ ```
28
+ Paste relevant output from .tracker.log here
29
+ ```
@@ -0,0 +1,16 @@
1
+ ---
2
+ name: Feature Request
3
+ about: Suggest a new feature or improvement
4
+ title: ''
5
+ labels: enhancement
6
+ assignees: ''
7
+ ---
8
+
9
+ **Problem**
10
+ What are you trying to do that you can't do today?
11
+
12
+ **Proposed solution**
13
+ How would you like it to work?
14
+
15
+ **Alternatives considered**
16
+ Any other approaches you thought about.
@@ -0,0 +1,17 @@
1
+ ## What
2
+
3
+ Brief description of the change.
4
+
5
+ ## Why
6
+
7
+ What problem does this solve?
8
+
9
+ ## How
10
+
11
+ Key implementation details (if non-obvious).
12
+
13
+ ## Testing
14
+
15
+ - [ ] Imports clean: `uv run python -c "import main, tracker, dashboard, db"`
16
+ - [ ] Dashboard tested manually
17
+ - [ ] No personal data in committed files
@@ -0,0 +1,129 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ pull_request:
7
+ branches: [main]
8
+
9
+ permissions:
10
+ contents: read
11
+
12
+ jobs:
13
+ lint:
14
+ name: Lint & Format
15
+ runs-on: ubuntu-latest
16
+ steps:
17
+ - uses: actions/checkout@v4
18
+ - uses: astral-sh/setup-uv@v6
19
+ - uses: actions/setup-python@v5
20
+ with:
21
+ python-version: "3.13"
22
+
23
+ - name: Install dependencies
24
+ run: uv sync --extra dev
25
+
26
+ - name: Ruff check
27
+ run: uv run ruff check .
28
+
29
+ - name: Ruff format check
30
+ run: uv run ruff format --check .
31
+
32
+ typecheck:
33
+ name: Import & Syntax Check
34
+ runs-on: ubuntu-latest
35
+ strategy:
36
+ matrix:
37
+ python-version: ["3.11", "3.12", "3.13"]
38
+ steps:
39
+ - uses: actions/checkout@v4
40
+ - uses: astral-sh/setup-uv@v6
41
+ - uses: actions/setup-python@v5
42
+ with:
43
+ python-version: ${{ matrix.python-version }}
44
+
45
+ - name: Install dependencies
46
+ run: uv sync --extra dev
47
+
48
+ - name: Verify all modules import
49
+ run: uv run python -c "import main, tracker, dashboard, db, cookie_store, get_cookies; print('All imports OK')"
50
+
51
+ - name: Check for syntax errors
52
+ run: uv run python -m py_compile main.py && uv run python -m py_compile tracker.py && uv run python -m py_compile dashboard.py && uv run python -m py_compile db.py && uv run python -m py_compile cookie_store.py && uv run python -m py_compile get_cookies.py
53
+
54
+ test:
55
+ name: Tests
56
+ runs-on: ubuntu-latest
57
+ strategy:
58
+ matrix:
59
+ python-version: ["3.11", "3.12", "3.13"]
60
+ steps:
61
+ - uses: actions/checkout@v4
62
+ - uses: astral-sh/setup-uv@v6
63
+ - uses: actions/setup-python@v5
64
+ with:
65
+ python-version: ${{ matrix.python-version }}
66
+
67
+ - name: Install dependencies
68
+ run: uv sync --extra dev
69
+
70
+ - name: Run tests
71
+ run: uv run pytest tests/ -v --tb=short || echo "No tests found yet"
72
+
73
+ security:
74
+ name: Security Scan
75
+ runs-on: ubuntu-latest
76
+ steps:
77
+ - uses: actions/checkout@v4
78
+ - uses: astral-sh/setup-uv@v6
79
+ - uses: actions/setup-python@v5
80
+ with:
81
+ python-version: "3.13"
82
+
83
+ - name: Install dependencies
84
+ run: uv sync --extra dev
85
+
86
+ - name: Check for hardcoded secrets
87
+ run: |
88
+ echo "Scanning for potential secrets..."
89
+ FOUND=0
90
+ # Check for hardcoded emails (not in example/help text)
91
+ if grep -rn '@gmail.com' --include='*.py' | grep -v 'you@gmail.com' | grep -v 'test@test.com' | grep -v '#' | grep -v 'example'; then
92
+ echo "::warning::Possible hardcoded email found"
93
+ FOUND=1
94
+ fi
95
+ # Check for API keys or tokens
96
+ if grep -rniE '(api_key|api_secret|token|password)\s*=' --include='*.py' | grep -v '#' | grep -v 'def ' | grep -v 'request' | grep -v 'csrf'; then
97
+ echo "::warning::Possible hardcoded credential found"
98
+ FOUND=1
99
+ fi
100
+ # Verify sensitive files are gitignored
101
+ for f in cookies.txt cookies.enc location_history.json location_history.db .tracker.log browser_profile; do
102
+ if ! grep -q "$f" .gitignore; then
103
+ echo "::error::$f is NOT in .gitignore"
104
+ FOUND=1
105
+ fi
106
+ done
107
+ if [ "$FOUND" -eq 0 ]; then echo "No secrets found."; fi
108
+
109
+ - name: Dependency audit
110
+ run: uv run pip audit --desc || echo "pip-audit not available, skipping"
111
+
112
+ build:
113
+ name: Package Build
114
+ runs-on: ubuntu-latest
115
+ needs: [lint, typecheck]
116
+ steps:
117
+ - uses: actions/checkout@v4
118
+ - uses: astral-sh/setup-uv@v6
119
+ - uses: actions/setup-python@v5
120
+ with:
121
+ python-version: "3.13"
122
+
123
+ - name: Build wheel
124
+ run: uv build
125
+
126
+ - name: Verify wheel contents
127
+ run: |
128
+ ls -la dist/
129
+ uv run python -m zipfile -l dist/*.whl | head -30
@@ -0,0 +1,34 @@
1
+ name: Publish to PyPI
2
+
3
+ on:
4
+ release:
5
+ types: [published]
6
+
7
+ permissions:
8
+ contents: read
9
+
10
+ jobs:
11
+ publish:
12
+ name: Build & Publish
13
+ runs-on: ubuntu-latest
14
+ environment: pypi
15
+ steps:
16
+ - uses: actions/checkout@v4
17
+ - uses: astral-sh/setup-uv@v6
18
+ - uses: actions/setup-python@v5
19
+ with:
20
+ python-version: "3.13"
21
+
22
+ - name: Install dependencies
23
+ run: uv sync --extra dev
24
+
25
+ - name: Run tests
26
+ run: uv run pytest tests/ -v --tb=short
27
+
28
+ - name: Build package
29
+ run: uv build
30
+
31
+ - name: Publish to PyPI
32
+ env:
33
+ UV_PUBLISH_TOKEN: ${{ secrets.PYPI_API_TOKEN }}
34
+ run: uv publish
@@ -0,0 +1,20 @@
1
+ # Python-generated files
2
+ __pycache__/
3
+ *.py[oc]
4
+ build/
5
+ dist/
6
+ wheels/
7
+ *.egg-info
8
+
9
+ # Virtual environments
10
+ .venv
11
+
12
+ # Sensitive data - NEVER commit
13
+ cookies.txt
14
+ cookies.enc
15
+ location_history.json
16
+ location_history.db
17
+ browser_profile/
18
+ .tracker.log*
19
+ .tracker.pid
20
+ todo.md
@@ -0,0 +1 @@
1
+ 3.13
@@ -0,0 +1,86 @@
1
+ # Contributing to Location Tracker
2
+
3
+ Thanks for your interest in contributing! This project is open to contributions of all kinds: bug reports, feature requests, documentation improvements, and code changes.
4
+
5
+ ## Getting Started
6
+
7
+ 1. Fork the repo and clone your fork
8
+ 2. Run `./setup.sh` or manually: `uv sync && uv run location-tracker setup`
9
+ 3. Configure: `uv run location-tracker config --email you@gmail.com`
10
+ 4. Authenticate: `uv run location-tracker cookies`
11
+ 5. Start developing: `uv run location-tracker on`
12
+
13
+ ## Development Setup
14
+
15
+ ```bash
16
+ # Install dependencies
17
+ uv sync
18
+
19
+ # Run the dashboard in foreground (for development)
20
+ uv run python main.py _serve
21
+
22
+ # Run import check
23
+ uv run python -c "import main, tracker, dashboard, db, cookie_store"
24
+ ```
25
+
26
+ ## Project Structure
27
+
28
+ | File | Purpose |
29
+ |------|---------|
30
+ | `main.py` | CLI entry point, daemon management, setup commands |
31
+ | `tracker.py` | Location polling, statistics, static map generation |
32
+ | `dashboard.py` | Flask server, API endpoints |
33
+ | `db.py` | SQLite database layer |
34
+ | `cookie_store.py` | Encrypted cookie storage (Fernet + macOS Keychain) |
35
+ | `get_cookies.py` | Browser-based Google authentication |
36
+ | `templates/index.html` | Dashboard HTML |
37
+ | `static/style.css` | Dashboard styles |
38
+ | `static/app.js` | Dashboard JavaScript (Leaflet map, UI logic) |
39
+
40
+ ## How to Contribute
41
+
42
+ ### Bug Reports
43
+
44
+ Open an issue with:
45
+ - What you expected to happen
46
+ - What actually happened
47
+ - Steps to reproduce
48
+ - Your OS and Python version
49
+
50
+ ### Feature Requests
51
+
52
+ Open an issue describing:
53
+ - The problem you're trying to solve
54
+ - Your proposed solution
55
+ - Any alternatives you considered
56
+
57
+ ### Pull Requests
58
+
59
+ 1. Create a branch from `main`
60
+ 2. Make your changes
61
+ 3. Verify imports: `uv run python -c "import main, tracker, dashboard, db"`
62
+ 4. Test the dashboard manually: `uv run python main.py _serve`
63
+ 5. Open a PR with a clear description of what changed and why
64
+
65
+ ### Code Style
66
+
67
+ - Follow existing patterns in each file
68
+ - Use `log.info/warning/error` for logging, not `print()`
69
+ - Add input validation at system boundaries (API endpoints, CLI args)
70
+ - Use `datetime.now(timezone.utc)` for all timestamps
71
+ - Escape user-controlled data before rendering in HTML (`esc()` in app.js)
72
+
73
+ ### Areas Where Help is Wanted
74
+
75
+ Check the [issues labeled `help wanted`](https://github.com/dcondrey/location-tracker/labels/help%20wanted) for specific tasks. Some general areas:
76
+
77
+ - **Cross-platform support** -- Linux (Secret Service for keychain), Windows
78
+ - **Test suite** -- Unit tests for db.py, tracker.py, cookie_store.py
79
+ - **Notifications** -- Push notifications when someone arrives/leaves a geofence
80
+ - **Data visualization** -- Speed graphs, time-at-location charts, weekly summaries
81
+ - **Multi-provider support** -- Apple Find My, Samsung SmartThings, Life360
82
+ - **Performance** -- WebSocket push updates instead of 30s polling on the frontend
83
+
84
+ ## Code of Conduct
85
+
86
+ Be respectful. This is a personal project shared with the community. Treat others the way you'd want to be treated.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 David Condrey
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,182 @@
1
+ Metadata-Version: 2.4
2
+ Name: location-tracker
3
+ Version: 1.0.0
4
+ Summary: Self-hosted location tracking dashboard with encrypted cookies, SQLite storage, and adaptive polling
5
+ Project-URL: Homepage, https://github.com/dcondrey/location-tracker
6
+ Project-URL: Repository, https://github.com/dcondrey/location-tracker
7
+ Project-URL: Issues, https://github.com/dcondrey/location-tracker/issues
8
+ Author-email: David Condrey <davidcondrey@me.com>
9
+ License-Expression: MIT
10
+ License-File: LICENSE
11
+ Keywords: dashboard,geolocation,google-maps,location,self-hosted,tracking
12
+ Classifier: Development Status :: 4 - Beta
13
+ Classifier: Environment :: Console
14
+ Classifier: Environment :: Web Environment
15
+ Classifier: Intended Audience :: Developers
16
+ Classifier: License :: OSI Approved :: MIT License
17
+ Classifier: Operating System :: MacOS
18
+ Classifier: Programming Language :: Python :: 3.11
19
+ Classifier: Programming Language :: Python :: 3.12
20
+ Classifier: Programming Language :: Python :: 3.13
21
+ Classifier: Topic :: System :: Monitoring
22
+ Requires-Python: >=3.11
23
+ Requires-Dist: cryptography>=44.0
24
+ Requires-Dist: flask>=3.1.0
25
+ Requires-Dist: folium>=0.20.0
26
+ Requires-Dist: locationsharinglib>=5.0.3
27
+ Requires-Dist: pandas>=3.0.3
28
+ Requires-Dist: playwright-stealth>=2.0.3
29
+ Requires-Dist: playwright>=1.60.0
30
+ Requires-Dist: schedule>=1.2.2
31
+ Provides-Extra: build
32
+ Requires-Dist: pyinstaller>=6.0; extra == 'build'
33
+ Provides-Extra: dev
34
+ Requires-Dist: pip-audit>=2.7; extra == 'dev'
35
+ Requires-Dist: pytest>=8.0; extra == 'dev'
36
+ Requires-Dist: ruff>=0.11; extra == 'dev'
37
+ Description-Content-Type: text/markdown
38
+
39
+ # Location Tracker
40
+
41
+ A self-hosted location tracking dashboard that polls Google Maps location sharing and visualizes movement history on an interactive map. Runs as a background daemon with a real-time web interface.
42
+
43
+ ## Features
44
+
45
+ - **Real-time tracking** -- Polls Google Maps shared locations with adaptive intervals (15s when driving, 10min when stationary)
46
+ - **Interactive dashboard** -- Dark-themed Leaflet map with path visualization, heatmaps, stop detection, and timeline scrubbing
47
+ - **Self-tracking** -- Track your own position via browser geolocation
48
+ - **Encrypted cookie storage** -- Google auth tokens encrypted at rest with Fernet; key stored in macOS Keychain
49
+ - **Auto cookie refresh** -- Headless browser automatically re-authenticates when cookies expire
50
+ - **SQLite storage** -- Location history stored in an indexed SQLite database with WAL mode
51
+ - **Mobile responsive** -- Bottom-sheet sidebar on phones, touch-friendly controls
52
+ - **Multiple export formats** -- JSON, CSV, and GeoJSON
53
+ - **Persistent daemon** -- Optional launchd integration to survive reboots
54
+ - **CLI query tools** -- Look up anyone's latest location or history from the terminal
55
+
56
+ ## Quick Start
57
+
58
+ ```bash
59
+ # Clone and set up
60
+ git clone https://github.com/dcondrey/location-tracker.git
61
+ cd location-tracker
62
+ ./setup.sh
63
+
64
+ # Or manually:
65
+ uv sync
66
+ uv run location-tracker setup
67
+
68
+ # Configure your Google account
69
+ uv run location-tracker config --email you@gmail.com
70
+
71
+ # Authenticate with Google (opens browser)
72
+ uv run location-tracker cookies
73
+
74
+ # Start tracking
75
+ uv run location-tracker on
76
+ ```
77
+
78
+ The dashboard will be available at **http://tracker** (or `http://localhost:7070` if DNS isn't configured).
79
+
80
+ ## Prerequisites
81
+
82
+ - **Python 3.11+**
83
+ - **macOS** (uses Keychain for cookie encryption, launchd for persistence)
84
+ - **uv** package manager ([install](https://docs.astral.sh/uv/getting-started/installation/))
85
+ - A Google account with [location sharing](https://support.google.com/maps/answer/7326816) enabled
86
+
87
+ ## Commands
88
+
89
+ ### Core
90
+
91
+ | Command | Description |
92
+ |---------|-------------|
93
+ | `on` | Start the tracker daemon and web dashboard |
94
+ | `off` | Stop the tracker |
95
+ | `status` | Check if the tracker is running |
96
+ | `cookies` | Open browser to authenticate with Google |
97
+ | `test` | Verify cookies are valid and list shared contacts |
98
+
99
+ ### Configuration
100
+
101
+ | Command | Description |
102
+ |---------|-------------|
103
+ | `config --email you@gmail.com` | Set the Google account email |
104
+ | `config` | Show current configuration |
105
+ | `setup` | First-time setup: install Chromium, configure DNS and port forwarding |
106
+ | `dns` | Set up `http://tracker` hostname |
107
+ | `dns --remove` | Remove hostname and port forwarding |
108
+ | `install` | Install as a launchd service (auto-start on login) |
109
+ | `install --remove` | Remove the launchd service |
110
+
111
+ ### Data
112
+
113
+ | Command | Description |
114
+ |---------|-------------|
115
+ | `where <person>` | Show someone's latest known location |
116
+ | `history <person> --days 7` | Show recent location history |
117
+ | `stats` | Print tracking statistics (distance, stops, dwell time) |
118
+ | `map --days 7 --output map.html` | Generate a static HTML map |
119
+ | `purge <days>` | Delete location records older than N days |
120
+
121
+ ## Dashboard
122
+
123
+ The web dashboard provides:
124
+
125
+ - **Map views** -- Road, Satellite, Hybrid, Terrain, and Dark map layers via Google/CARTO tiles
126
+ - **Visualization modes** -- Path view (color-coded routes with stop nodes), Heatmap, and Points
127
+ - **Time filtering** -- 24h, 3 days, 7 days, 30 days, 90 days, or all time
128
+ - **Timeline scrubber** -- Drag to view historical positions with date/time labels
129
+ - **Person cards** -- Click to focus; shows speed badge (Stationary/Walking/Driving/Highway)
130
+ - **Self-tracking** -- Enable browser geolocation to appear on the map yourself
131
+ - **Export** -- Download data as JSON, CSV, or GeoJSON
132
+ - **Toast notifications** -- Visual feedback for all actions
133
+
134
+ ## How It Works
135
+
136
+ ### Polling
137
+
138
+ The tracker polls Google Maps location sharing via [`locationsharinglib`](https://github.com/costastf/locationsharinglib). Polling frequency adapts to detected movement speed:
139
+
140
+ | Speed | Category | Poll Interval |
141
+ |-------|----------|--------------|
142
+ | > 60 km/h | Highway | 15 seconds |
143
+ | 10-60 km/h | Driving | 30 seconds |
144
+ | 1-10 km/h | Walking | 60 seconds |
145
+ | < 1 km/h | Stationary | 10 minutes |
146
+
147
+ The person being tracked receives no notification. This is a passive read of data they have already chosen to share.
148
+
149
+ ### Security
150
+
151
+ - **Cookie encryption** -- Google auth cookies are encrypted with `cryptography.Fernet` before writing to disk. The encryption key is stored in macOS Keychain, never on the filesystem.
152
+ - **Localhost only** -- The Flask server binds to `127.0.0.1`; not accessible from the network.
153
+ - **XSS protection** -- All user-controlled data is HTML-escaped before rendering.
154
+ - **Input validation** -- Lat/lon bounds checking, type coercion, and error handling on all API endpoints.
155
+ - **Atomic writes** -- SQLite with WAL mode for concurrent safety.
156
+
157
+ ### Data Storage
158
+
159
+ Location history is stored in a local SQLite database (`location_history.db`) with indexed columns for fast queries. Existing `location_history.json` files are automatically migrated on first run.
160
+
161
+ ## Project Structure
162
+
163
+ ```
164
+ location-tracker/
165
+ main.py # CLI entry point and daemon management
166
+ tracker.py # Location polling, stats, and map generation
167
+ dashboard.py # Flask web server and API endpoints
168
+ db.py # SQLite database layer
169
+ cookie_store.py # Encrypted cookie storage (Fernet + Keychain)
170
+ get_cookies.py # Browser-based Google authentication
171
+ templates/
172
+ index.html # Dashboard HTML
173
+ static/
174
+ style.css # Dashboard styles
175
+ app.js # Dashboard JavaScript
176
+ setup.sh # One-command install script
177
+ build.sh # PyInstaller standalone build
178
+ ```
179
+
180
+ ## License
181
+
182
+ MIT
@@ -0,0 +1,144 @@
1
+ # Location Tracker
2
+
3
+ A self-hosted location tracking dashboard that polls Google Maps location sharing and visualizes movement history on an interactive map. Runs as a background daemon with a real-time web interface.
4
+
5
+ ## Features
6
+
7
+ - **Real-time tracking** -- Polls Google Maps shared locations with adaptive intervals (15s when driving, 10min when stationary)
8
+ - **Interactive dashboard** -- Dark-themed Leaflet map with path visualization, heatmaps, stop detection, and timeline scrubbing
9
+ - **Self-tracking** -- Track your own position via browser geolocation
10
+ - **Encrypted cookie storage** -- Google auth tokens encrypted at rest with Fernet; key stored in macOS Keychain
11
+ - **Auto cookie refresh** -- Headless browser automatically re-authenticates when cookies expire
12
+ - **SQLite storage** -- Location history stored in an indexed SQLite database with WAL mode
13
+ - **Mobile responsive** -- Bottom-sheet sidebar on phones, touch-friendly controls
14
+ - **Multiple export formats** -- JSON, CSV, and GeoJSON
15
+ - **Persistent daemon** -- Optional launchd integration to survive reboots
16
+ - **CLI query tools** -- Look up anyone's latest location or history from the terminal
17
+
18
+ ## Quick Start
19
+
20
+ ```bash
21
+ # Clone and set up
22
+ git clone https://github.com/dcondrey/location-tracker.git
23
+ cd location-tracker
24
+ ./setup.sh
25
+
26
+ # Or manually:
27
+ uv sync
28
+ uv run location-tracker setup
29
+
30
+ # Configure your Google account
31
+ uv run location-tracker config --email you@gmail.com
32
+
33
+ # Authenticate with Google (opens browser)
34
+ uv run location-tracker cookies
35
+
36
+ # Start tracking
37
+ uv run location-tracker on
38
+ ```
39
+
40
+ The dashboard will be available at **http://tracker** (or `http://localhost:7070` if DNS isn't configured).
41
+
42
+ ## Prerequisites
43
+
44
+ - **Python 3.11+**
45
+ - **macOS** (uses Keychain for cookie encryption, launchd for persistence)
46
+ - **uv** package manager ([install](https://docs.astral.sh/uv/getting-started/installation/))
47
+ - A Google account with [location sharing](https://support.google.com/maps/answer/7326816) enabled
48
+
49
+ ## Commands
50
+
51
+ ### Core
52
+
53
+ | Command | Description |
54
+ |---------|-------------|
55
+ | `on` | Start the tracker daemon and web dashboard |
56
+ | `off` | Stop the tracker |
57
+ | `status` | Check if the tracker is running |
58
+ | `cookies` | Open browser to authenticate with Google |
59
+ | `test` | Verify cookies are valid and list shared contacts |
60
+
61
+ ### Configuration
62
+
63
+ | Command | Description |
64
+ |---------|-------------|
65
+ | `config --email you@gmail.com` | Set the Google account email |
66
+ | `config` | Show current configuration |
67
+ | `setup` | First-time setup: install Chromium, configure DNS and port forwarding |
68
+ | `dns` | Set up `http://tracker` hostname |
69
+ | `dns --remove` | Remove hostname and port forwarding |
70
+ | `install` | Install as a launchd service (auto-start on login) |
71
+ | `install --remove` | Remove the launchd service |
72
+
73
+ ### Data
74
+
75
+ | Command | Description |
76
+ |---------|-------------|
77
+ | `where <person>` | Show someone's latest known location |
78
+ | `history <person> --days 7` | Show recent location history |
79
+ | `stats` | Print tracking statistics (distance, stops, dwell time) |
80
+ | `map --days 7 --output map.html` | Generate a static HTML map |
81
+ | `purge <days>` | Delete location records older than N days |
82
+
83
+ ## Dashboard
84
+
85
+ The web dashboard provides:
86
+
87
+ - **Map views** -- Road, Satellite, Hybrid, Terrain, and Dark map layers via Google/CARTO tiles
88
+ - **Visualization modes** -- Path view (color-coded routes with stop nodes), Heatmap, and Points
89
+ - **Time filtering** -- 24h, 3 days, 7 days, 30 days, 90 days, or all time
90
+ - **Timeline scrubber** -- Drag to view historical positions with date/time labels
91
+ - **Person cards** -- Click to focus; shows speed badge (Stationary/Walking/Driving/Highway)
92
+ - **Self-tracking** -- Enable browser geolocation to appear on the map yourself
93
+ - **Export** -- Download data as JSON, CSV, or GeoJSON
94
+ - **Toast notifications** -- Visual feedback for all actions
95
+
96
+ ## How It Works
97
+
98
+ ### Polling
99
+
100
+ The tracker polls Google Maps location sharing via [`locationsharinglib`](https://github.com/costastf/locationsharinglib). Polling frequency adapts to detected movement speed:
101
+
102
+ | Speed | Category | Poll Interval |
103
+ |-------|----------|--------------|
104
+ | > 60 km/h | Highway | 15 seconds |
105
+ | 10-60 km/h | Driving | 30 seconds |
106
+ | 1-10 km/h | Walking | 60 seconds |
107
+ | < 1 km/h | Stationary | 10 minutes |
108
+
109
+ The person being tracked receives no notification. This is a passive read of data they have already chosen to share.
110
+
111
+ ### Security
112
+
113
+ - **Cookie encryption** -- Google auth cookies are encrypted with `cryptography.Fernet` before writing to disk. The encryption key is stored in macOS Keychain, never on the filesystem.
114
+ - **Localhost only** -- The Flask server binds to `127.0.0.1`; not accessible from the network.
115
+ - **XSS protection** -- All user-controlled data is HTML-escaped before rendering.
116
+ - **Input validation** -- Lat/lon bounds checking, type coercion, and error handling on all API endpoints.
117
+ - **Atomic writes** -- SQLite with WAL mode for concurrent safety.
118
+
119
+ ### Data Storage
120
+
121
+ Location history is stored in a local SQLite database (`location_history.db`) with indexed columns for fast queries. Existing `location_history.json` files are automatically migrated on first run.
122
+
123
+ ## Project Structure
124
+
125
+ ```
126
+ location-tracker/
127
+ main.py # CLI entry point and daemon management
128
+ tracker.py # Location polling, stats, and map generation
129
+ dashboard.py # Flask web server and API endpoints
130
+ db.py # SQLite database layer
131
+ cookie_store.py # Encrypted cookie storage (Fernet + Keychain)
132
+ get_cookies.py # Browser-based Google authentication
133
+ templates/
134
+ index.html # Dashboard HTML
135
+ static/
136
+ style.css # Dashboard styles
137
+ app.js # Dashboard JavaScript
138
+ setup.sh # One-command install script
139
+ build.sh # PyInstaller standalone build
140
+ ```
141
+
142
+ ## License
143
+
144
+ MIT