aboutsummaryrefslogtreecommitdiff
path: root/apps/web/lib/createEmbeds.ts
blob: e3f67340e812f7fa4ae4f3162b36d107f82507ff (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
import {
	AssetRecordType,
	Editor,
	TLAsset,
	TLAssetId,
	TLExternalContentSource,
	VecLike,
	getEmbedInfo,
	getHashForString,
} from "tldraw";
import { createEmptyBookmarkShape } from "./drophelpers";
import { unfirlSite } from "@/app/actions/fetchers";

export default async function createEmbedsFromUrl({
	url,
	point,
	sources,
	editor,
}: {
	url: string;
	point?: VecLike | undefined;
	sources?: TLExternalContentSource[] | undefined;
	editor: Editor;
}) {
	const position =
		point ??
		(editor.inputs.shiftKey
			? editor.inputs.currentPagePoint
			: editor.getViewportPageBounds().center);

	const urlPattern = /https?:\/\/(x\.com|twitter\.com)\/[\w]+\/[\w]+\/[\d]+/;
	if (urlPattern.test(url)) {
		return editor.createShape({
			type: "Twittercard",
			x: position.x - 250,
			y: position.y - 150,
			props: { url: url },
		});
	}

	// try to paste as an embed first
	const embedInfo = getEmbedInfo(url);

	if (embedInfo) {
		return editor.putExternalContent({
			type: "embed",
			url: embedInfo.url,
			point,
			embed: embedInfo.definition,
		});
	}

	const assetId: TLAssetId = AssetRecordType.createId(getHashForString(url));
	const shape = createEmptyBookmarkShape(editor, url, position);

	let asset = editor.getAsset(assetId) as TLAsset;
	let shouldAlsoCreateAsset = false;
	if (!asset) {
		shouldAlsoCreateAsset = true;
		try {
			const bookmarkAsset = await editor.getAssetForExternalContent({
				type: "url",
				url,
			});
			const value = await unfirlSite(url);
			if (bookmarkAsset) {
				if (bookmarkAsset.type === "bookmark") {
					if (value.title) bookmarkAsset.props.title = value.title;
					if (value.image) bookmarkAsset.props.image = value.image;
					if (value.description)
						bookmarkAsset.props.description = value.description;
				}
			}
			if (!bookmarkAsset) throw Error("Could not create an asset");
			asset = bookmarkAsset;
		} catch (e) {
			console.log(e);
			return;
		}
	}

	editor.batch(() => {
		if (shouldAlsoCreateAsset) {
			editor.createAssets([asset]);
		}

		editor.updateShapes([
			{
				id: shape.id,
				type: shape.type,
				props: {
					assetId: asset.id,
				},
			},
		]);
	});
}