tangled
alpha
login
or
join now
leaflet.pub
/
leaflet
a tool for shared writing and social publishing
275
fork
atom
overview
issues
24
pulls
pipelines
add page for boris
awarm.space
5 months ago
5635885d
4442d76b
+135
3 changed files
expand all
collapse all
unified
split
app
lish
sorry-boris
fixFeeds.ts
fixFeedsButton.tsx
page.tsx
+35
app/lish/sorry-boris/fixFeeds.ts
···
1
1
+
"use server";
2
2
+
3
3
+
import { AppBskyActorDefs, Agent as BskyAgent } from "@atproto/api";
4
4
+
import { getIdentityData } from "actions/getIdentityData";
5
5
+
import { createOauthClient } from "src/atproto-oauth";
6
6
+
const leafletFeedURI =
7
7
+
"at://did:plc:btxrwcaeyodrap5mnjw2fvmz/app.bsky.feed.generator/subscribedPublications";
8
8
+
9
9
+
export async function fixFeeds() {
10
10
+
const oauthClient = await createOauthClient();
11
11
+
let identity = await getIdentityData();
12
12
+
if (!identity || !identity.atp_did) {
13
13
+
throw new Error("Invalid identity data");
14
14
+
}
15
15
+
16
16
+
let credentialSession = await oauthClient.restore(identity.atp_did);
17
17
+
let bsky = new BskyAgent(credentialSession);
18
18
+
let prefs = await bsky.app.bsky.actor.getPreferences();
19
19
+
let savedFeeds = prefs.data.preferences.find(
20
20
+
(pref) => pref.$type === "app.bsky.actor.defs#savedFeedsPrefV2",
21
21
+
) as AppBskyActorDefs.SavedFeedsPrefV2;
22
22
+
23
23
+
let pubFeeds = savedFeeds.items.filter(
24
24
+
(feed) => feed.value === leafletFeedURI,
25
25
+
);
26
26
+
await bsky.removeSavedFeeds(pubFeeds.map((f) => f.id));
27
27
+
28
28
+
await bsky.addSavedFeeds([
29
29
+
{
30
30
+
value: leafletFeedURI,
31
31
+
pinned: true,
32
32
+
type: "feed",
33
33
+
},
34
34
+
]);
35
35
+
}
+31
app/lish/sorry-boris/fixFeedsButton.tsx
···
1
1
+
"use client";
2
2
+
3
3
+
import { useSmoker } from "components/Toast";
4
4
+
import { fixFeeds } from "./fixFeeds";
5
5
+
import { ButtonPrimary } from "components/Buttons";
6
6
+
import { DotLoader } from "components/utils/DotLoader";
7
7
+
import { useState } from "react";
8
8
+
9
9
+
export function FixFeedsButton() {
10
10
+
let smoker = useSmoker();
11
11
+
let [loading, setLoading] = useState(false);
12
12
+
return (
13
13
+
<ButtonPrimary
14
14
+
onClick={async (e) => {
15
15
+
let rect = e.currentTarget?.getBoundingClientRect();
16
16
+
setLoading(true);
17
17
+
await fixFeeds();
18
18
+
setLoading(false);
19
19
+
smoker({
20
20
+
position: {
21
21
+
x: rect.left + (rect.right - rect.left) / 2,
22
22
+
y: rect.top - 16,
23
23
+
},
24
24
+
text: "Fixed your feeds!",
25
25
+
});
26
26
+
}}
27
27
+
>
28
28
+
{loading ? <DotLoader /> : "Fix My Feeds"}
29
29
+
</ButtonPrimary>
30
30
+
);
31
31
+
}
+69
app/lish/sorry-boris/page.tsx
···
1
1
+
import { getIdentityData } from "actions/getIdentityData";
2
2
+
import { BlueskyLogin } from "app/login/LoginForm";
3
3
+
import { codeToHtml } from "shiki";
4
4
+
import { FixFeedsButton } from "./fixFeedsButton";
5
5
+
6
6
+
export default async function Page() {
7
7
+
let identity = await getIdentityData();
8
8
+
if (!identity) {
9
9
+
return (
10
10
+
<Layout>
11
11
+
<BlueskyLogin redirectRoute="/lish/sorry-boris" />
12
12
+
</Layout>
13
13
+
);
14
14
+
}
15
15
+
let code = await codeToHtml(source, {
16
16
+
lang: "typescript",
17
17
+
theme: "catppuccin-latte",
18
18
+
});
19
19
+
return (
20
20
+
<Layout>
21
21
+
<FixFeedsButton />
22
22
+
<pre dangerouslySetInnerHTML={{ __html: code }} />
23
23
+
</Layout>
24
24
+
);
25
25
+
}
26
26
+
27
27
+
function Layout(props: { children: React.ReactNode }) {
28
28
+
return (
29
29
+
<div className="flex flex-col items-center justify-center h-screen gap-4">
30
30
+
{props.children}
31
31
+
</div>
32
32
+
);
33
33
+
}
34
34
+
35
35
+
let source = `
36
36
+
import { AppBskyActorDefs, Agent as BskyAgent } from "@atproto/api";
37
37
+
import { getIdentityData } from "actions/getIdentityData";
38
38
+
import { createOauthClient } from "src/atproto-oauth";
39
39
+
const leafletFeedURI =
40
40
+
"at://did:plc:btxrwcaeyodrap5mnjw2fvmz/app.bsky.feed.generator/subscribedPublications";
41
41
+
42
42
+
export async function fixFeeds() {
43
43
+
const oauthClient = await createOauthClient();
44
44
+
let identity = await getIdentityData();
45
45
+
if (!identity || !identity.atp_did) {
46
46
+
throw new Error("Invalid identity data");
47
47
+
}
48
48
+
49
49
+
let credentialSession = await oauthClient.restore(identity.atp_did);
50
50
+
let bsky = new BskyAgent(credentialSession);
51
51
+
let prefs = await bsky.app.bsky.actor.getPreferences();
52
52
+
let savedFeeds = prefs.data.preferences.find(
53
53
+
(pref) => pref.$type === "app.bsky.actor.defs#savedFeedsPrefV2",
54
54
+
) as AppBskyActorDefs.SavedFeedsPrefV2;
55
55
+
56
56
+
let pubFeeds = savedFeeds.items.filter(
57
57
+
(feed) => feed.value === leafletFeedURI,
58
58
+
);
59
59
+
await bsky.removeSavedFeeds(pubFeeds.map((f) => f.id));
60
60
+
61
61
+
await bsky.addSavedFeeds([
62
62
+
{
63
63
+
value: leafletFeedURI,
64
64
+
pinned: true,
65
65
+
type: "feed",
66
66
+
},
67
67
+
]);
68
68
+
}
69
69
+
`;