Skip to content

Instantly share code, notes, and snippets.

@linyows
Last active June 1, 2020 02:47
Show Gist options
  • Save linyows/300d7cc1ab41fd62d81eb631e51da7e9 to your computer and use it in GitHub Desktop.
Save linyows/300d7cc1ab41fd62d81eb631e51da7e9 to your computer and use it in GitHub Desktop.
Detect public pages on notion.
import fetch from "node-fetch"
const sleep = msec => new Promise(resolve => setTimeout(resolve, msec))
type Page = {
id: string
title: string
isPublic: boolean
}
class Notion {
token: string
stackedPages: Page[]
spaceName: string
spaceId: string
public constructor(name: string, token: string) {
this.token = token
this.spaceName = name
}
public async request({ endpoint, body }) {
const url = "https://www.notion.so/api/v3/"
const headers = {
accept: "*/*",
"accept-language": "de-DE,de;q=0.9,en-US;q=0.8,en;q=0.7",
"content-type": "application/json",
cookie: `token_v2=${this.token};`
}
const jsonbody = JSON.stringify(body)
const res = await fetch(`${url}${endpoint}`, { headers, body: jsonbody, method: 'POST' })
return res.json()
}
public async getTopLevelPages(): Promise<Page[]> {
const res = await this.request({ endpoint: 'loadUserContent', body: {} })
Object.values(res.recordMap.space).map((v: any) => {
if (v.value.name === this.spaceName) {
this.spaceId = v.value.id
return
}
})
return Object.values(res.recordMap.block).map((v: any): Page => {
const { id, parent_id, properties, type, permissions } = v.value
if (parent_id === this.spaceId && properties && properties.hasOwnProperty('title')) {
return { id, title: properties.title.join(','), isPublic: this.isPublic(permissions) }
}
}).filter(el => {
return el !== undefined
}).filter((el, i, arr) => {
return arr.findIndex(ell => el.id === ell.id) === i
})
}
public isPublic(permissions: any[]|undefined): boolean {
if (permissions === undefined) {
return false
}
for (const o of permissions) {
if (o.type && o.type === 'public_permission') {
return true
}
}
return false
}
public async loadPageChunk(pageId: string): Promise<any[]> {
const body = {
pageId,
limit: 1000,
cursor: { stack: [] },
chunkNumber: 0,
verticalColumns: false
}
const res = await this.request({ endpoint: 'loadPageChunk', body })
if (res && res.recordMap && res.recordMap.hasOwnProperty('block')) {
return Object.values(res.recordMap.block)
}
return []
}
public async getChildPages(pageId: string): Promise<Page[]> {
const res = await this.loadPageChunk(pageId)
if (res.length === 0) {
return []
}
const columns = res.filter(el => { return el.value.type === 'column' })
const pages = await Promise.all(res.map(async (v: any): Promise<Page> => {
const { id, parent_id, properties, type, permissions } = v.value
if (type == 'page' && properties && properties.hasOwnProperty('title')) {
if (parent_id === pageId) {
return { id, title: properties.title.join(','), isPublic: this.isPublic(permissions) } as Page
} else {
if (columns.some(el => el.value.id === parent_id)) {
return { id, title: properties.title.join(','), isPublic: this.isPublic(permissions) } as Page
}
}
}
}))
return pages.filter(el => {
return el !== undefined
}).filter((el, i, arr) => {
return arr.findIndex(ell => el.id === ell.id) === i
})
}
public async getProgenyPages(pages) {
let foundPages = []
if (pages.length === 0) {
return foundPages
}
for (const page of pages) {
process.stdout.write('.')
//console.log(page)
await sleep(1000)
const gotPages = await this.getChildPages(page.id)
for (const gotPage of gotPages) {
if (this.stackedPages.some(el => el.id === gotPage.id)) {
continue
}
foundPages.push(gotPage)
}
}
this.stackedPages = this.stackedPages.concat(...foundPages).filter((el, i, arr) => {
return arr.findIndex(ell => el.id === ell.id) === i
})
await this.getProgenyPages(foundPages)
}
public async getAll() {
const pages: Page[] = await this.getTopLevelPages()
this.stackedPages = []
await this.getProgenyPages(pages)
process.stdout.write('\n')
const publics = this.stackedPages.filter((el, i, arr) => {
return el.isPublic
})
console.log(publics)
console.log(`${this.stackedPages.length} pages`)
}
}
const client = new Notion(process.env.WORKSPACE, process.env.TOKEN)
client.getAll()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment