Last active
November 19, 2023 00:37
-
-
Save bpevs/0c4a61701bd3d345382848de6faf577f to your computer and use it in GitHub Desktop.
Parse Google Takeout results into a geojson file
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Google maps does already export to geo-json, but that doesn't take lists | |
// into account. This script maps the `Saved` csv files, maps data to | |
// `Maps (your places)`, and outputs a set of geojson files for each list. | |
// Requirements: | |
// - All locations must be "starred". This puts it in the "Saved Places.json". | |
//. - Notes can be in a list location. | |
// - Lists must NOT HAVE a "List description". It fucks up the csv parsing. | |
// Once you verify this, create a Google takeout that includes: | |
// - Maps (your places) | |
// - Saved | |
// Place the export into the same dir as this, rename to `takeout`, then run: | |
// deno run --allow-read --allow-write ./takout_to_geojson.js | |
import { parse, stringify } from "https://deno.land/[email protected]/csv/mod.ts"; | |
import { ensureDir } from 'https://deno.land/[email protected]/fs/mod.ts' | |
const decoder = new TextDecoder("utf-8"); | |
await ensureDir("./results/lists") | |
const placesData = await Deno.readFile( | |
"./takeout/Maps (your places)/Saved Places.json", | |
); | |
const places = JSON.parse(decoder.decode(placesData)); | |
const unnamedPlaces = []; | |
const placesByName = {}; | |
places.features.forEach((place) => { | |
const placeName = place.properties?.location?.name; | |
if (!placeName) return unnamedPlaces.push(place); | |
placesByName[placeName] = place; | |
}); | |
for await (const dirEntry of Deno.readDir("./takeout/Saved")) { | |
const name = dirEntry.name.split(".")[0]; | |
const features = []; | |
const listData = await Deno.readFile(`./takeout/Saved/${dirEntry.name}`); | |
const list = parse(decoder.decode(listData), { skipFirstRow: true }); | |
list.forEach((row) => { | |
const { Title, Note, URL, Comment } = row; | |
const place = placesByName[Title]; | |
if (!place) return; | |
place.properties.timestamp = place.properties.date; | |
place.properties.Name = place.properties.Title; | |
place.properties.description = Note; | |
delete place.properties.Title; | |
delete place.properties.date; | |
features.push(place); | |
}); | |
await Deno.writeTextFile( | |
`./results/lists/${name}.json`, | |
JSON.stringify({ name, type: "FeatureCollection", features }, null, 2), | |
); | |
} | |
Deno.writeTextFile("./results/unnamed_places.json", JSON.stringify(unnamedPlaces, null, 2)); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment