Skip to content

Get signed file URL endpoint proposal #49

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 25 commits into
base: master
Choose a base branch
from
Draft
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
Binary file added .DS_Store
Binary file not shown.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
dist
node_modules
worker
wrangler.toml
wrangler.toml
.wrangler
1 change: 1 addition & 0 deletions .ruby-version
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
2.5.3

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"rows":[{"id":"8902111b-71f7-4cd6-a3e0-8310802f0ba8","Name":"peter"},{"id":"e997a14f-f9b9-4dc4-b7e3-4b2ed540f9d6","Name":"jasper"},{"id":"6ee8139d-3ca4-4349-9dd6-600f95183e50","Name":"woof"}],"schema":{"@I]j":{"name":"Tags","type":"multi_select"},"title":{"name":"Name","type":"title"}},"name":"rabbits","tableArr":[{"value":{"id":"8902111b-71f7-4cd6-a3e0-8310802f0ba8","version":12,"type":"page","properties":{"title":[["peter"]]},"created_time":1689509699048,"last_edited_time":1689509704576,"parent_id":"85a1dee4-59a6-48fc-a5bc-a6d8531ac269","parent_table":"collection","alive":true,"created_by_table":"notion_user","created_by_id":"5eb42727-2109-44be-b04d-578a4950ef50","last_edited_by_table":"notion_user","last_edited_by_id":"5eb42727-2109-44be-b04d-578a4950ef50","space_id":"a8000652-f2c8-4adc-9353-cd51c033cc1f"},"role":"reader"},{"value":{"id":"e997a14f-f9b9-4dc4-b7e3-4b2ed540f9d6","version":14,"type":"page","properties":{"title":[["jasper"]]},"created_time":1689509699048,"last_edited_time":1689509708565,"parent_id":"85a1dee4-59a6-48fc-a5bc-a6d8531ac269","parent_table":"collection","alive":true,"created_by_table":"notion_user","created_by_id":"5eb42727-2109-44be-b04d-578a4950ef50","last_edited_by_table":"notion_user","last_edited_by_id":"5eb42727-2109-44be-b04d-578a4950ef50","space_id":"a8000652-f2c8-4adc-9353-cd51c033cc1f"},"role":"reader"},{"value":{"id":"6ee8139d-3ca4-4349-9dd6-600f95183e50","version":10,"type":"page","properties":{"title":[["woof"]]},"created_time":1689509699048,"last_edited_time":1689509725934,"parent_id":"85a1dee4-59a6-48fc-a5bc-a6d8531ac269","parent_table":"collection","alive":true,"created_by_table":"notion_user","created_by_id":"5eb42727-2109-44be-b04d-578a4950ef50","last_edited_by_table":"notion_user","last_edited_by_id":"5eb42727-2109-44be-b04d-578a4950ef50","space_id":"a8000652-f2c8-4adc-9353-cd51c033cc1f"},"role":"reader"}],"columns":[{"width":276,"visible":true,"property":"title","name":"Name","type":"title"},{"visible":true,"property":"@I]j","name":"Tags","type":"multi_select"}],"collection":{"value":{"id":"85a1dee4-59a6-48fc-a5bc-a6d8531ac269","version":9,"name":[["rabbits"]],"schema":{"@I]j":{"name":"Tags","type":"multi_select"},"title":{"name":"Name","type":"title"}},"format":{"collection_page_properties":[{"visible":true,"property":"@I]j"}]},"parent_id":"808463d9-298c-42df-9a63-f6067de8bd95","parent_table":"block","alive":true,"migrated":true,"space_id":"a8000652-f2c8-4adc-9353-cd51c033cc1f"},"role":"reader"},"sort":["8902111b-71f7-4cd6-a3e0-8310802f0ba8","e997a14f-f9b9-4dc4-b7e3-4b2ed540f9d6","6ee8139d-3ca4-4349-9dd6-600f95183e50"],"views":[{"id":"3ecce580-8344-42b7-96c5-5b9de945a31d","version":1,"type":"table","format":{"table_wrap":true,"table_properties":[{"width":276,"visible":true,"property":"title","name":"Name","type":"title"},{"visible":true,"property":"@I]j","name":"Tags","type":"multi_select"}],"collection_pointer":{"id":"85a1dee4-59a6-48fc-a5bc-a6d8531ac269","table":"collection","spaceId":"a8000652-f2c8-4adc-9353-cd51c033cc1f"}},"parent_id":"808463d9-298c-42df-9a63-f6067de8bd95","parent_table":"block","alive":true,"page_sort":["8902111b-71f7-4cd6-a3e0-8310802f0ba8","e997a14f-f9b9-4dc4-b7e3-4b2ed540f9d6","6ee8139d-3ca4-4349-9dd6-600f95183e50"],"space_id":"a8000652-f2c8-4adc-9353-cd51c033cc1f"},{"id":"c299b379-0b56-4221-a665-8401546223f6","version":2,"type":"table","format":{"table_wrap":false,"table_properties":[{"wrap":true,"width":100,"visible":true,"property":"{jf|"},{"wrap":false,"width":222,"visible":true,"property":"title"},{"wrap":false,"width":409,"visible":true,"property":"R`]x"},{"wrap":false,"width":100,"visible":true,"property":"nxhL"},{"wrap":true,"width":100,"visible":true,"property":"CzHM"},{"wrap":false,"width":316,"visible":false,"property":"~bt\\"},{"wrap":false,"width":100,"visible":true,"property":"BOur"},{"wrap":false,"width":100,"visible":true,"property":"SJm?"},{"wrap":false,"width":100,"visible":true,"property":"qH[K"},{"wrap":false,"width":200,"visible":true,"property":"VZAs"},{"wrap":false,"width":200,"visible":true,"property":"UdGI"},{"wrap":false,"width":200,"visible":true,"property":"nnr{"},{"visible":true,"property":"xOrL"}],"collection_pointer":{"id":"4c5375b2-34ac-48e6-b11a-822cfd16a25e","table":"collection","spaceId":"a8000652-f2c8-4adc-9353-cd51c033cc1f"}},"parent_id":"dff5d33f-c8de-49c6-b57e-9dee74c51e8c","parent_table":"block","alive":true,"page_sort":["d8ebf362-63cf-41b6-a019-66e26ac8e21b","af6c8c8e-5b7a-4646-942e-ae7e7af03e0a","8e0fb8f8-5c93-4600-9a04-fe3e673a35a6","60794889-12e5-484e-a9d1-70ab7b51a799","8600f00b-1886-48b6-86f7-d10cd11636e1","b619bf36-c430-46c8-b4e3-8553f96a0bf8","ed95fdca-499c-40ab-87b6-3a8dec0c7c2e","9eda27cc-ac50-4665-affe-2c7b9d393496","4f2785cc-30d0-4462-b55b-03ec61ec8223","6ee750d2-0dad-4726-8110-9af53e07f0f8","7b67d2b8-8f2a-4be9-a55c-dbd72af5e824","ce3b2e90-56b5-45b3-9746-b9d8380b9feb","a0e7da18-99e7-476d-9fc7-ce40d3d9ac5e","d41c153a-a7f7-4390-99b9-b175b15ff3bb","1434d49f-0826-4dbe-874e-9fa160091306","dbd6405c-4206-4939-a2ae-957dbfe985be","5c3a6ee0-fa82-4328-8800-7dc1e358f2ef","890e1b05-339f-4f70-a21b-bbb24cee8968","5c487e9d-ef99-4a74-bb29-f29182534ad8","f7da0a06-5716-4d18-9fe4-c49760a00383","736cd137-a233-4891-a871-a36ffd7f0f16","05a1da7b-00e7-4cdd-9410-7e9480eb4a77","c0247cec-af5c-471f-bd90-88b31d6c260e","2d3b53f3-ba80-4c1c-ad77-908f8efae199","8167c14e-f1ca-4db4-aa60-d0d65f4c3690","f7da7951-a377-45e1-9d7d-87fc71cf8b76","3c28a3b4-14c1-4a9b-9fb4-96c817b24c2d","ccdd0b02-a8a0-4bf9-907c-4dd8be639836","d87a85e4-d3f0-41ff-863d-7e7beaeee22d","a7bed94a-cdb6-4896-a5b4-3e2e943f1097","41c1e0a6-1d1e-4214-a0e8-3375ce76818c","b5a91f81-649b-4d2c-be25-3a91e05eff98","b7b7b529-09da-4318-a504-2649bd045086"],"space_id":"a8000652-f2c8-4adc-9353-cd51c033cc1f"},{"id":"ba601f1c-872a-4179-8bb5-bc80646b99bf","version":22,"type":"table","format":{"table_wrap":true,"table_properties":[{"width":207,"visible":true,"property":"title"},{"width":200,"visible":true,"property":"zxl<"},{"width":313,"visible":true,"property":"CbSI"},{"width":369,"visible":true,"property":"KeGT"}],"collection_pointer":{"id":"035b5a75-25f8-4ae8-acca-2bf6e7557189","table":"collection","spaceId":"a8000652-f2c8-4adc-9353-cd51c033cc1f"},"collection_page_properties":[{"visible":true,"property":"Y>Aw"}]},"parent_id":"0f9f24f8-2570-4411-86a8-c10d9f788412","parent_table":"block","alive":true,"page_sort":["bc1b9d83-c82d-48e3-bed9-8e05ad55e942","5301eb0e-59ce-4eb1-b881-2ec7069a724a","8ad364a0-576b-4b77-b071-acce2760240b","07d1e163-d344-4407-b5d4-11a850a33160","d7bfdda6-5885-4763-b74c-a130c769b14a","65cad99e-a6af-43bd-9b53-fb9f3a62ad19","3abb17b2-5d4e-4a77-a2cc-736c73ef5932"],"space_id":"a8000652-f2c8-4adc-9353-cd51c033cc1f"}]}

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Binary file added .wrangler/state/v3/cache/default/db.sqlite
Binary file not shown.
11 changes: 7 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
{
"name": "notion-api-worker",
"version": "0.1.0",
"version": "0.1.",
"main": "dist/index.js",
"license": "MIT",
"scripts": {
"build": "webpack",
"dev": "wrangler dev",
"dev": "wrangler dev --port 8787",
"preview": "wrangler preview",
"deploy": "wrangler publish -e production"
"deploy": "wrangler deploy",
"prod": "wrangler deploy"
},
"dependencies": {
"global": "^4.4.0",
"tiny-request-router": "^1.2.2"
},
"devDependencies": {
Expand All @@ -20,6 +22,7 @@
"ts-loader": "^8.0.1",
"typescript": "^3.9.7",
"webpack": "^4.43.0",
"webpack-cli": "^3.3.12"
"webpack-cli": "^3.3.12",
"wrangler": "^3.15.0"
}
}
140 changes: 99 additions & 41 deletions src/api/notion.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@

import {
JSONData,
NotionUserType,
Expand All @@ -22,21 +23,32 @@ const loadPageChunkBody = {
verticalColumns: false,
};

let ctr=0

const fetchNotionData = async <T extends any>({
resource,
body,
notionToken,
}: INotionParams): Promise<T> => {
const res = await fetch(`${NOTION_API}/${resource}`, {
method: "POST",
headers: {
"content-type": "application/json",
...(notionToken && { cookie: `token_v2=${notionToken}` }),
},
body: JSON.stringify(body),
});

return res.json();
try {
const res = await fetch(`${NOTION_API}/${resource}`, {
method: "POST",
headers: {
"content-type": "application/json",
"referer": "https://phagedirectory.notion.site",
"origin": "https://phagedirectory.notion.site",
...(notionToken && { cookie: `token_v2=${notionToken}` }),
},

body: JSON.stringify(body),
});

let json = await res.json()
return json;
} catch(e) {
console.error('fetchNotionData error:', e)
throw new Error('Failed to pull data from Notion')
}
};

export const fetchPageById = async (pageId: string, notionToken?: string) => {
Expand All @@ -52,29 +64,48 @@ export const fetchPageById = async (pageId: string, notionToken?: string) => {
return res;
};

const queryCollectionBody = {
query: { aggregations: [{ property: "title", aggregator: "count" }] },
loader: {
type: "table",
limit: 999,
searchQuery: "",
userTimeZone: "Europe/Vienna",
userLocale: "en",
loadContentCover: true,
},
};

export const fetchTableData = async (
collectionId: string,
collectionViewId: string,
notionToken?: string
notionToken: string,
property_filter: any = {},
sort: any = [],
limit: Number,
) => {
const table = await fetchNotionData<CollectionData>({
resource: "queryCollection",
body: {
collectionId,
collectionViewId,
...queryCollectionBody,
collection: {
id: collectionId,
},
collectionView: {
id: collectionViewId,
},
loader: {
type: "reducer",
reducers: {
collection_group_results: {
type: "results",
// limit: 50,
// limit: 100,
// limit: 999,
limit: limit,
loadContentCover: true,
},
"table:uncategorized:title:count": {
type: "aggregation",
aggregation: {
property: "title",
aggregator: "count",
},
},
},
searchQuery: "",
userTimeZone: "Europe/Vienna",
filter: { operator: "and", filters: property_filter.filters },
sort,
limit,
}
},
notionToken,
});
Expand All @@ -94,14 +125,16 @@ export const fetchNotionUsers = async (
});
if (users && users.results) {
return users.results.map((u) => {
const user = {
id: u.value.id,
firstName: u.value.given_name,
lastLame: u.value.family_name,
fullName: u.value.given_name + " " + u.value.family_name,
profilePhoto: u.value.profile_photo,
};
return user;
if(u.value) {
const user = {
id: u.value.id,
firstName: u.value.given_name,
lastLame: u.value.family_name,
fullName: u.value.given_name + " " + u.value.family_name,
profilePhoto: u.value.profile_photo,
};
return user;
}
});
}
return [];
Expand All @@ -114,17 +147,42 @@ export const fetchBlocks = async (
return await fetchNotionData<LoadPageChunkData>({
resource: "syncRecordValues",
body: {
recordVersionMap: {
block: blockList.reduce((obj, blockId) => {
obj[blockId] = -1;
return obj;
}, {} as { [key: string]: -1 }),
},
requests: blockList.map((id) => ({
id,
table: "block",
version: -1,
})),
},
notionToken,
});
};


export const fetchNotionAsset = async (
fileUrl: string,
blockId: string,
) => {
return await fetchNotionData({
resource: "getSignedFileUrls",
body: {
urls: [
{
url: fileUrl,
permissionRecord: {
table: "block",
id: blockId
}
}
]
},
});
};






export const fetchNotionSearch = async (
params: NotionSearchParamsType,
notionToken?: string
Expand Down Expand Up @@ -154,4 +212,4 @@ export const fetchNotionSearch = async (
},
notionToken,
});
};
};
8 changes: 7 additions & 1 deletion src/api/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ export type ColumnType =

export type ColumnSchemaType = {
name: string;
options: string[];
type: ColumnType;
};

Expand All @@ -56,13 +57,15 @@ export type RowContentType =
| number
| string[]
| { title: string; id: string }
| { type:string, start_date:string, end_date?:string, end_time?:string, time_zone?: string, start_time?:string, date_format?:string }
| UserType[]
| DecorationType[]
| { name: string; url: string }[];

export interface BaseValueType {
id: string;
type: string;
view_ids?: string[];
version: number;
created_time: number;
last_edited_time: number;
Expand Down Expand Up @@ -94,6 +97,7 @@ export interface RowType {
value: {
id: string;
parent_id: string;
format: any;
properties: { [key: string]: DecorationType[] };
};
}
Expand Down Expand Up @@ -165,7 +169,9 @@ export interface CollectionData {
};
};
result: {
blockIds: string[];
reducerResults: {
collection_group_results: { blockIds: string[] };
};
};
}

Expand Down
45 changes: 41 additions & 4 deletions src/api/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,16 +26,21 @@ export const getNotionValue = (
): RowContentType => {
switch (type) {
case "text":
return getTextContent(val);
// return val; // includes formatted content like bold and anchors, but a pain to parse
// return getTextContent(val);
return getFormattedTextContent(val);
case "person":
return (
val.filter((v) => v.length > 1).map((v) => v[1]![0][1] as string) || []
);
case "checkbox":
return val[0][0] === "Yes";
case "date":
if (val[0][1]![0][0] === "d") return val[0]![1]![0]![1]!.start_date;
else return "";
if (val[0][1]! && val[0][1]![0][0] === "d") {
return val[0]![1]![0]![1];
}
else
return "";
case "title":
return getTextContent(val);
case "select":
Expand All @@ -52,11 +57,15 @@ export const getNotionValue = (
.filter(([symbol]) => symbol === "‣")
.map(([_, relation]) => relation![0][1] as string);
case "file":
if(!val[0][1]) // file is embedded link
return [{'name': val[0][0].toString(), 'url': val[0][0].toString()}]

return val
.filter((v) => v.length > 1)
.map((v) => {
const rawUrl = v[1]![0][1] as string;

const rawUrl = v[1]![0][1] as string;

const url = new URL(
`https://www.notion.so${
rawUrl.startsWith("/image")
Expand All @@ -80,3 +89,31 @@ export const getNotionValue = (
const getTextContent = (text: DecorationType[]) => {
return text.reduce((prev, current) => prev + current[0], "");
};


const getFormattedTextContent = (text: DecorationType[]) => {
// console.log('---text:', text[0])
// return text.reduce((prev, current) => {
// console.log('p/c', prev, current)
// return prev + current[0]}, "");
const newtext = text
.map(text =>
text[1]
? text[1].reduceRight(
(av, cv) =>
({
i: `<em>${av}</em>`,
c: `<code class="notion-inline-code">${av}</code>`,
s: `<s>${av}</s>`,
b: `<b>${av}</b>`,
h: `<span class="notion-${cv[1]}">${av}</span>`,
a: `<a class="notion-link" href="${cv[1]}">${av}</a>`,
}[cv[0]]),
text[0]
)
: text[0]
)
.join('')

return newtext
};
Loading