tangled
alpha
login
or
join now
leaflet.pub
/
leaflet
289
fork
atom
a tool for shared writing and social publishing
289
fork
atom
overview
issues
28
pulls
pipelines
add pub favicon
awarm.space
6 months ago
6475948f
351abf1a
+65
-7
2 changed files
expand all
collapse all
unified
split
app
layout.tsx
lish
[did]
[publication]
icon.ts
-7
app/layout.tsx
···
14
14
title: "Leaflet",
15
15
description: "tiny interconnected social documents",
16
16
metadataBase: new URL(`https://leaflet.pub`),
17
17
-
icons: [
18
18
-
{
19
19
-
type: "apple-touch-icon",
20
20
-
sizes: "180x180",
21
21
-
url: "/apple-touch-icon.png",
22
22
-
},
23
23
-
],
24
17
appleWebApp: {
25
18
title: "Leaflet",
26
19
statusBarStyle: "black-translucent",
+65
app/lish/[did]/[publication]/icon.ts
···
1
1
+
import { NextRequest } from "next/server";
2
2
+
import { IdResolver } from "@atproto/identity";
3
3
+
import { AtUri } from "@atproto/syntax";
4
4
+
import { PubLeafletPublication } from "lexicons/api";
5
5
+
import { supabaseServerClient } from "supabase/serverClient";
6
6
+
import sharp from "sharp";
7
7
+
8
8
+
let idResolver = new IdResolver();
9
9
+
10
10
+
export const size = {
11
11
+
width: 32,
12
12
+
height: 32,
13
13
+
};
14
14
+
15
15
+
export const contentType = "image/png";
16
16
+
export default async function Icon({
17
17
+
params,
18
18
+
}: {
19
19
+
params: { did: string; publication: string };
20
20
+
}) {
21
21
+
let did = decodeURIComponent(params.did);
22
22
+
let uri;
23
23
+
if (/^(?!\.$|\.\.S)[A-Za-z0-9._:~-]{1,512}$/.test(params.publication)) {
24
24
+
uri = AtUri.make(
25
25
+
did,
26
26
+
"pub.leaflet.publication",
27
27
+
params.publication,
28
28
+
).toString();
29
29
+
}
30
30
+
let { data: publication } = await supabaseServerClient
31
31
+
.from("publications")
32
32
+
.select(
33
33
+
`*,
34
34
+
publication_subscriptions(*),
35
35
+
documents_in_publications(documents(*))
36
36
+
`,
37
37
+
)
38
38
+
.eq("identity_did", did)
39
39
+
.or(`name.eq."${params.publication}", uri.eq."${uri}"`)
40
40
+
.single();
41
41
+
42
42
+
let record = publication?.record as PubLeafletPublication.Record | null;
43
43
+
if (!record?.icon) return null;
44
44
+
45
45
+
let identity = await idResolver.did.resolve(did);
46
46
+
let service = identity?.service?.find((f) => f.id === "#atproto_pds");
47
47
+
console.log(identity);
48
48
+
if (!service) return null;
49
49
+
let cid = (record.icon.ref as unknown as { $link: string })["$link"];
50
50
+
const response = await fetch(
51
51
+
`${service.serviceEndpoint}/xrpc/com.atproto.sync.getBlob?did=${did}&cid=${cid}`,
52
52
+
);
53
53
+
let blob = await response.blob();
54
54
+
let resizedImage = await sharp(await blob.arrayBuffer())
55
55
+
.resize({ width: 32, height: 32 })
56
56
+
.toBuffer();
57
57
+
console.log("fetched favicon!");
58
58
+
return new Response(new Uint8Array(resizedImage), {
59
59
+
headers: {
60
60
+
"Content-Type": "image/png",
61
61
+
"CDN-Cache-Control": "s-max-age=86400, stale-while-revalidate=86400",
62
62
+
"Cache-Control": "public, max-age=3600",
63
63
+
},
64
64
+
});
65
65
+
}