Skip to content

Instantly share code, notes, and snippets.

@bpevs
Last active November 19, 2023 00:37
Show Gist options
  • Save bpevs/0c4a61701bd3d345382848de6faf577f to your computer and use it in GitHub Desktop.
Save bpevs/0c4a61701bd3d345382848de6faf577f to your computer and use it in GitHub Desktop.
Parse Google Takeout results into a geojson file
// 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