Skip to content

Commit 0475fc1

Browse files
authored
Merge pull request #1823 from mfts/fix/notion
feat: add separate function to fix internal notion api change
2 parents 073ee9d + 1be839f commit 0475fc1

File tree

4 files changed

+113
-8
lines changed

4 files changed

+113
-8
lines changed

components/documents/add-document-modal.tsx

Lines changed: 26 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import { DefaultPermissionStrategy } from "@prisma/client";
99
import { parsePageId } from "notion-utils";
1010
import { toast } from "sonner";
1111
import { mutate } from "swr";
12+
import { z } from "zod";
1213

1314
import { useAnalytics } from "@/lib/analytics";
1415
import {
@@ -18,6 +19,7 @@ import {
1819
} from "@/lib/documents/create-document";
1920
import { putFile } from "@/lib/files/put-file";
2021
import { useDataroomPermissions } from "@/lib/hooks/use-dataroom-permissions";
22+
import { getNotionPageIdFromSlug } from "@/lib/notion/utils";
2123
import { usePlan } from "@/lib/swr/use-billing";
2224
import { useDataroom } from "@/lib/swr/use-dataroom";
2325
import useLimits from "@/lib/swr/use-limits";
@@ -387,17 +389,35 @@ export function AddDocumentModal({
387389
return;
388390
}
389391

390-
const validateNotionPageURL = parsePageId(notionLink);
391-
// Check if it's a valid URL or not by Regx
392-
const isValidURL =
393-
/^(https?:\/\/)?([a-zA-Z0-9-]+\.){1,}[a-zA-Z]{2,}([a-zA-Z0-9-._~:/?#[\]@!$&'()*+,;=]+)?$/;
394-
395392
// Check if the field is empty or not
396393
if (!notionLink) {
397394
toast.error("Please enter a Notion link to proceed.");
398395
return; // prevent form from submitting
399396
}
400-
if (validateNotionPageURL === null || !isValidURL.test(notionLink)) {
397+
398+
// Validate URL format with Zod
399+
const urlSchema = z.string().url();
400+
const urlValidation = urlSchema.safeParse(notionLink);
401+
402+
if (!urlValidation.success) {
403+
toast.error("Please enter a valid URL format.");
404+
return;
405+
}
406+
407+
// Try to validate the Notion page URL
408+
let validateNotionPageURL = parsePageId(notionLink);
409+
410+
// If parsePageId fails, try to get page ID from slug
411+
if (validateNotionPageURL === null) {
412+
try {
413+
validateNotionPageURL = await getNotionPageIdFromSlug(notionLink);
414+
} catch (slugError) {
415+
toast.error("Please enter a valid Notion link to proceed.");
416+
return;
417+
}
418+
}
419+
420+
if (!validateNotionPageURL) {
401421
toast.error("Please enter a valid Notion link to proceed.");
402422
return;
403423
}

lib/api/documents/process-document.ts

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { parsePageId } from "notion-utils";
33
import { DocumentData } from "@/lib/documents/create-document";
44
import { copyFileToBucketServer } from "@/lib/files/copy-file-to-bucket-server";
55
import notion from "@/lib/notion";
6+
import { getNotionPageIdFromSlug } from "@/lib/notion/utils";
67
import prisma from "@/lib/prisma";
78
import { convertCadToPdfTask } from "@/lib/trigger/convert-files";
89
import { convertFilesToPdfTask } from "@/lib/trigger/convert-files";
@@ -49,7 +50,17 @@ export const processDocument = async ({
4950
// Check whether the Notion page is publically accessible or not
5051
if (type === "notion") {
5152
try {
52-
const pageId = parsePageId(key, { uuid: false });
53+
let pageId = parsePageId(key, { uuid: false });
54+
55+
// If parsePageId fails, try to get page ID from slug
56+
if (!pageId) {
57+
try {
58+
pageId = await getNotionPageIdFromSlug(key);
59+
} catch (slugError) {
60+
throw new Error("Unable to extract page ID from Notion URL");
61+
}
62+
}
63+
5364
// if the page isn't accessible then end the process here.
5465
if (!pageId) {
5566
throw new Error("Notion page not found");

lib/notion/index.ts

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,26 @@
11
import { NotionAPI } from "notion-client";
22

3-
const notion = new NotionAPI();
3+
const notion = new NotionAPI({
4+
kyOptions: {
5+
hooks: {
6+
beforeRequest: [
7+
(request, options) => {
8+
const url = request.url.toString();
9+
10+
if (url.includes("/api/v3/syncRecordValues")) {
11+
return new Request(
12+
url.replace(
13+
"/api/v3/syncRecordValues",
14+
"/api/v3/syncRecordValuesMain",
15+
),
16+
options,
17+
);
18+
}
19+
20+
return request;
21+
},
22+
],
23+
},
24+
},
25+
});
426
export default notion;

lib/notion/utils.ts

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,3 +74,55 @@ export const addSignedUrls: NotionAPI["addSignedUrls"] = async ({
7474
}
7575
}
7676
};
77+
78+
export async function getNotionPageIdFromSlug(url: string) {
79+
// Parse the URL to extract domain and slug
80+
const urlObj = new URL(url);
81+
const hostname = urlObj.hostname;
82+
83+
// Extract domain from hostname (e.g., "domain" from "domain.notion.site")
84+
const domainMatch = hostname.match(/^([^.]+)\.notion\.site$/);
85+
if (!domainMatch) {
86+
throw new Error("Invalid Notion site URL format: ${url}");
87+
}
88+
89+
const spaceDomain = domainMatch[1];
90+
91+
// Extract slug from pathname (remove leading slash)
92+
// If slug is missing, we will try to get page just by using spaceDomain
93+
let slug = urlObj.pathname.substring(1) || "";
94+
95+
// Make request to Notion's internal API
96+
const apiUrl =
97+
"https://${spaceDomain}.notion.site/api/v3/getPublicPageDataForDomain";
98+
const payload = {
99+
type: "block-space",
100+
name: "page",
101+
slug: slug,
102+
spaceDomain: spaceDomain,
103+
requestedOnPublicDomain: true,
104+
};
105+
106+
const response = await fetch(apiUrl, {
107+
method: "POST",
108+
headers: {
109+
"Content-Type": "application/json",
110+
"User-Agent": "Mozilla/5.0 (compatible; MyApp/1.0)",
111+
},
112+
body: JSON.stringify(payload),
113+
});
114+
115+
if (!response.ok) {
116+
throw new Error(
117+
"Notion API request failed: ${response.status} ${response.statusText}",
118+
);
119+
}
120+
121+
const data = await response.json();
122+
123+
if (data.pageId) {
124+
return data.pageId;
125+
} else {
126+
throw new Error("No pageId found in Notion API response");
127+
}
128+
}

0 commit comments

Comments
 (0)