Skip to content
Open

Idk #36

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -109,3 +109,5 @@ markdown
markdown.zip
.envrc
json/

backups
30 changes: 19 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@

# notion-backup

This is a very simple tool to export a workspace from [Notion](https://www.notion.so/), designed
Expand All @@ -18,10 +17,10 @@ Automatically downloading backups from Notion requires two unique authentication
4. Insert `getSpaces` into the search filter of the Network tab. This should give you one result. Click on it.
5. In the Preview tab, look for the key `space`. There you should find a list of all the workspaces you have access to. Unless you're part of shared workspaces there should only be one.
6. Copy the UUID of the workspace you want to backup (e.g. `6e560115-7a65-4f65-bb04-1825b43748f1`). This is your `NOTION_SPACE_ID`.
6. Switch to the Application (Chrome, Edge) or Storage (Firefox, Safari) tab on the top.
7. In the left sidebar, select `Cookies` -> `https://www.notion.so` (Chrome, Edge, Firefox) or `Cookies – https://www.notion.so` (Safari).
8. Copy the value of `token_v2` as your `NOTION_TOKEN` and the value of `file_token` as your `NOTION_FILE_TOKEN`.
9. Set the three environment variables as secrets for actions in your GitHub repository.
7. Switch to the Application (Chrome, Edge) or Storage (Firefox, Safari) tab on the top.
8. In the left sidebar, select `Cookies` -> `https://www.notion.so` (Chrome, Edge, Firefox) or `Cookies – https://www.notion.so` (Safari).
9. Copy the value of `token_v2` as your `NOTION_TOKEN` and the value of `file_token` as your `NOTION_FILE_TOKEN`.
10. Set the three environment variables as secrets for actions in your GitHub repository.

**NOTE**: if you log out of your account or your session expires naturally, the `NOTION_TOKEN` and `NOTION_FILE_TOKEN` will get invalidated and the backup will fail. In this case you need to obtain new tokens by repeating this process. There is currently no practical way to automize this until Notion decide to add a backup endpoint to their official API, at which point this script will be able to use a proper authentication token.

Expand All @@ -35,7 +34,8 @@ This assumes you are looking to set this up to back up Notion to GitHub.
4. Give Actions write access to your repository: `Settings` > `Actions` > `General` > `Workflow permissions` > choose `Read and write permissions`
5. Install the following under `.github/workflows/whatever.yml` in your repo.
6. Configure the frequency by changing the `cron` value. You can use [Crontab.guru](https://crontab.guru/#0_*/4_*_*_*).
7. Push and control your backup workflow from the `Actions` tab of your repository Github page.
7. Configure the time zone and locale by changing the `NOTION_TIME_ZONE` and `NOTION_LOCALE` value. ([Timezones](https://momentjs.com/timezone/))
8. Push and control your backup workflow from the `Actions` tab of your repository Github page.

```yaml
name: "Notion backup"
Expand All @@ -62,9 +62,6 @@ jobs:
with:
node-version: '18'

- name: Delete previous backup
run: rm -rf markdown html *.zip

- name: Setup dependencies
run: npm install -g notion-backup

Expand All @@ -74,13 +71,15 @@ jobs:
NOTION_TOKEN: ${{ secrets.NOTION_TOKEN }}
NOTION_FILE_TOKEN: ${{ secrets.NOTION_FILE_TOKEN }}
NOTION_SPACE_ID: ${{ secrets.NOTION_SPACE_ID }}
NOTION_TIME_ZONE: 'America/New_York'
NOTION_LOCALE: 'en'
NODE_OPTIONS: "--max-http-header-size 15000"

- name: Delete zips
run: |
rm -f *.zip
rm -f markdown/*-Part*.zip
rm -f html/*-Part*.zip
find markdown -name "*-Part*.zip" -type f -exec rm -f {} \;
find html -name "*-Part*.zip" -type f -exec rm -f {} \;

- name: Commit changes
run: |
Expand All @@ -102,3 +101,12 @@ You won't be able to backup files exceeding a size of 100MB unless you enable [G
*.jpeg filter=lfs diff=lfs merge=lfs -text
*.psd filter=lfs diff=lfs merge=lfs -text
```

## [Windows: Git filename too long](https://stackoverflow.com/questions/22575662/filename-too-long-in-git-for-windows)

1. Enable long paths in Windows: [Tutorial](https://www.microfocus.com/documentation/filr/filr-4/filr-desktop/t47bx2ogpfz7.html)
2. Enable long paths in Git:

```shell
git config core.longpaths true
```
47 changes: 47 additions & 0 deletions local-backup.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
const { exec } = require("child_process");
const { mkdir, opendir } = require("fs/promises");
require("dotenv").config();
const nb = require("./notion-backup");

async function run() {
if (!process.env.NOTION_BACKUP_DIR) {
console.log("Env variable NOTION_BACKUP_DIR needs to be specified.");
process.exit(1);
}

await mkdir(process.env.NOTION_BACKUP_DIR, { recursive: true });

await nb.run();

exec(
`cd ${process.env.NOTION_BACKUP_DIR};` +
"rm -f *.zip;" +
'find markdown -name "*-Part*.zip" -type f -delete ;' +
'find html -name "*-Part*.zip" -type f -delete ;',
(_, stdout, stderr) => {
if (stderr) console.log("STDOUT:", stdout, ", STDERR:", stderr);
}
);
}

async function dwada() {
const dir = await opendir(process.env.NOTION_BACKUP_DIR, {
recursive: true,
});

for await (let dirent of dir) {
console.log(dirent.name);
/*
if (!dirent.isDirectory()) continue;

const innerDir = await opendir(
`${process.env.NOTION_BACKUP_DIR}\\${dirent.name}`
);
for await (let innerDirent of innerDir) {
console.log(innerDirent.name);
}*/
}
}

//run();
dwada();
67 changes: 33 additions & 34 deletions notion-backup-item.js
Original file line number Diff line number Diff line change
@@ -1,51 +1,50 @@
#!/usr/bin/env node

let { program } = require('commander')
, { writeFileSync, mkdirSync } = require('fs')
, { join, isAbsolute, dirname } = require('path')
, { NotionAPI } = require('notion-client')
, { parsePageId } = require('notion-utils')
, { NOTION_TOKEN } = process.env
, nc = new NotionAPI({ authToken: NOTION_TOKEN })
, die = (str) => {
console.error(str);
process.exit(1);
}
;

let { program } = require("commander"),
{ writeFileSync, mkdirSync } = require("fs"),
{ join, isAbsolute, dirname } = require("path"),
{ NotionAPI } = require("notion-client"),
{ parsePageId } = require("notion-utils"),
{ NOTION_TOKEN, NOTION_BACKUP_DIR } = process.env,
nc = new NotionAPI({ authToken: NOTION_TOKEN }),
die = (str) => {
console.error(str);
process.exit(1);
};
// --version
program.version(require('./package.json').version);
program.version(require("./package.json").version);

program
.option('-i, --id <id>', 'ID of the Notion document')
.option('-c, --collection <collection>', 'ID of the Notion collection')
.option('-v, --view <view>', 'ID of the Notion collection view')
.option('-o, --out <file>', 'File to write to')
;
.option("-i, --id <id>", "ID of the Notion document")
.option("-c, --collection <collection>", "ID of the Notion collection")
.option("-v, --view <view>", "ID of the Notion collection view")
.option("-o, --out <file>", "File to write to");

// now do something
program.parse(process.argv);

async function run () {
let { id, collection, view, out } = program.opts()
, refPage
;
async function run() {
let { id, collection, view, out } = program.opts(),
refPage;
if (collection) {
if (!view) die('The --collection option requires --view to also be specified.');
if (id) console.warn('Warning: --id will be ignored.');
refPage = await nc.getCollectionData(parsePageId(collection), parsePageId(view));
}
else if (id) {
if (view) console.warn('Warning: --view will be ignored.');
if (!view)
die("The --collection option requires --view to also be specified.");
if (id) console.warn("Warning: --id will be ignored.");
refPage = await nc.getCollectionData(
parsePageId(collection),
parsePageId(view)
);
} else if (id) {
if (view) console.warn("Warning: --view will be ignored.");
refPage = await nc.getPage(parsePageId(id));
}
else die('Must specify one of --id or --collection/--view.');
} else die("Must specify one of --id or --collection/--view.");
let json = JSON.stringify(refPage, null, 2);
if (out) {
let file = isAbsolute(out) ? out : join(process.cwd(), out);
let file = isAbsolute(out)
? out
: join(NOTION_BACKUP_DIR ?? process.cwd(), out);
mkdirSync(dirname(file), { recursive: true });
writeFileSync(file, json);
}
else process.stdout.write(json);
} else process.stdout.write(json);
}
run();
Loading