Skip to content

Commit bfdca1b

Browse files
committed
Improve handlers.
1 parent d7d0b44 commit bfdca1b

File tree

1 file changed

+87
-25
lines changed

1 file changed

+87
-25
lines changed

src/pages/api/buffer_posts.ts

Lines changed: 87 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,57 @@
11
import { getCollection, getEntry } from "astro:content";
22
import type { APIRoute } from "astro";
33

4+
// Get @username from Twitter URL
5+
function getTwitterUsername(url: string): string | undefined {
6+
if (!url) return undefined;
7+
const username = url.split("/").pop();
8+
return (username ?? url).startsWith("@") ? username : `@${username}`;
9+
}
10+
11+
// Get @username from Bluesky URL
12+
function getBlueskyUsername(url: string): string | undefined {
13+
if (!url) return undefined;
14+
const username = url.split("/").pop()?.replace(/^@/, "");
15+
return username ? `@${username}` : undefined;
16+
}
17+
18+
// Get Bluesky profile link from username
19+
function getBlueskyProfileLink(username: string): string {
20+
// Remove any leading @ if present
21+
const cleanUsername = username.replace(/^@/, "");
22+
return `https://bsky.app/profile/${cleanUsername}`;
23+
}
24+
25+
// Get @username@instance.tld from Mastodon URL
26+
function getMastodonUsername(url: string): string | undefined {
27+
if (!url) return undefined;
28+
const match = url.match(/https?:\/\/([^\/]+)\/@([^\/]+)(\/|\?|$)/);
29+
return match ? `@${match[2]}@${match[1]}` : undefined;
30+
}
31+
32+
function getLinkedInUsernameHandler(url: string): string | undefined {
33+
if (!url) return undefined;
34+
const match = url.match(/https?:\/\/([^\/]+)\/in\/([^\/]+)(\/|\?|$)/);
35+
if (match) {
36+
try {
37+
return `https://www.linkedin.com/in/${decodeURIComponent(match[2])}`;
38+
} catch {
39+
return `https://www.linkedin.com/in/${match[2]}`;
40+
}
41+
}
42+
return undefined;
43+
}
44+
445
export const GET: APIRoute = async ({ params, request }) => {
546
const limit = Infinity;
647
const speakers = await getCollection("speakers");
7-
848
const exclude = [
949
"sebastian-ramirez",
1050
"savannah-ostrowski",
1151
"nerea-luis",
1252
"petr-baudis",
1353
"brett-cannon",
1454
];
15-
1655
const records: any[] = [];
1756

1857
const charLimits: Record<string, number> = {
@@ -23,17 +62,31 @@ export const GET: APIRoute = async ({ params, request }) => {
2362
fosstodon: 500,
2463
};
2564

26-
const message_template_full = ({
27-
name,
28-
talkTitle,
29-
talkUrl,
30-
fallbackUrl,
31-
}: {
32-
name: string;
33-
talkTitle: string;
34-
talkUrl: string;
35-
fallbackUrl: string;
36-
}) => `Join ${name} at EuroPython for “${talkTitle}”.`;
65+
// Tailor message templates for each platform using appropriate handle formats
66+
const message_template = {
67+
instagram: ({ name, talkTitle, talkUrl }) =>
68+
`Join ${name} at EuroPython for "${talkTitle}". Check the link in bio for details!`,
69+
70+
x: ({ name, handle, talkTitle, talkUrl }) =>
71+
handle
72+
? `Join ${name} (${handle}) at EuroPython for "${talkTitle}". ${talkUrl}`
73+
: `Join ${name} at EuroPython for "${talkTitle}". ${talkUrl}`,
74+
75+
linkedin: ({ name, handle, talkTitle, talkUrl }) =>
76+
handle
77+
? `Join ${name} (${handle}) at EuroPython for "${talkTitle}". ${talkUrl}`
78+
: `Join ${name} at EuroPython for "${talkTitle}". ${talkUrl}`,
79+
80+
bsky: ({ name, handle, talkTitle, talkUrl }) =>
81+
handle
82+
? `Join ${name} (${handle}) at EuroPython for "${talkTitle}". ${talkUrl}`
83+
: `Join ${name} at EuroPython for "${talkTitle}". ${talkUrl}`,
84+
85+
fosstodon: ({ name, handle, talkTitle, talkUrl }) =>
86+
handle
87+
? `Join ${name} (${handle}) at EuroPython for "${talkTitle}". ${talkUrl}`
88+
: `Join ${name} at EuroPython for "${talkTitle}". ${talkUrl}`,
89+
};
3790

3891
const trimToLimit = (text: string, limit: number) =>
3992
text.length <= limit ? text : text.slice(0, limit - 1) + "…";
@@ -58,37 +111,46 @@ export const GET: APIRoute = async ({ params, request }) => {
58111
const validSessions = sessions.filter(
59112
(session) => session && session.data.title
60113
);
114+
61115
if (validSessions.length === 0) continue;
62116

63117
const talkTitle = validSessions[0]?.data.title || "an exciting topic";
64118
const talkCode = validSessions[0]?.data.code;
65-
66119
const talkUrl = `https://ep2025.europython.eu/${talkCode}`;
67120
const speakerImage = `https://ep2025-buffer.ep-preview.click/media/social-${speaker.id}.png`;
68121
const fallbackUrl = `https://ep2025.europython.eu/speaker/${speaker.id}`;
69-
const links = {
70-
instagram: fallbackUrl,
71-
x: twitter_url ?? fallbackUrl,
72-
linkedin: linkedin_url ?? fallbackUrl,
73-
bsky: bluesky_url ?? fallbackUrl,
74-
fosstodon: mastodon_url ?? fallbackUrl,
122+
123+
// Extract handles for each platform
124+
const handles = {
125+
x: getTwitterUsername(twitter_url || ""),
126+
linkedin: getLinkedInUsernameHandler(linkedin_url || ""),
127+
bsky: getBlueskyUsername(bluesky_url || ""),
128+
fosstodon: getMastodonUsername(mastodon_url || ""),
75129
};
76130

77-
const generateMessage = (platform: string) => {
78-
const full = message_template_full({
131+
// Generate appropriate messages for each platform
132+
const generateMessage = (platform: keyof typeof message_template) => {
133+
const templateFn = message_template[platform];
134+
const handle =
135+
platform === "instagram"
136+
? undefined
137+
: handles[platform as keyof typeof handles];
138+
139+
const full = templateFn({
79140
name,
141+
handle,
80142
talkTitle,
81-
talkUrl,
82-
fallbackUrl: links[platform],
143+
talkUrl: platform === "instagram" ? fallbackUrl : talkUrl,
83144
});
84-
const limit = charLimits[platform];
85145

146+
const limit = charLimits[platform];
86147
return trimToLimit(full, limit);
87148
};
88149

89150
const record = {
90151
name,
91152
image: speakerImage,
153+
handles: handles,
92154
channel: {
93155
instagram: generateMessage("instagram"),
94156
x: generateMessage("x"),

0 commit comments

Comments
 (0)