Refactor Webmentions component to fetch mentions directly and improve data handling
All checks were successful
Deploy / deploy (push) Successful in 1m17s
All checks were successful
Deploy / deploy (push) Successful in 1m17s
This commit is contained in:
parent
5c73ede1e0
commit
1d57e23d19
1 changed files with 50 additions and 11 deletions
|
|
@ -1,7 +1,21 @@
|
||||||
---
|
---
|
||||||
import { DEFAULT_LOCALE, type Locale } from '~/consts';
|
import { DEFAULT_LOCALE, type Locale } from '~/consts';
|
||||||
import { getLocaleFromUrl, t } from '~/i18n/ui';
|
import { getLocaleFromUrl, t } from '~/i18n/ui';
|
||||||
import { getMentionsFor, groupMentions, type WMEntry } from '~/lib/webmentions';
|
|
||||||
|
interface WMAuthor {
|
||||||
|
name?: string;
|
||||||
|
url?: string;
|
||||||
|
photo?: string;
|
||||||
|
}
|
||||||
|
interface WMEntry {
|
||||||
|
author?: WMAuthor;
|
||||||
|
url: string;
|
||||||
|
published?: string;
|
||||||
|
'wm-received'?: string;
|
||||||
|
'wm-id'?: number;
|
||||||
|
'wm-property'?: string;
|
||||||
|
content?: { text?: string };
|
||||||
|
}
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
target: string | URL;
|
target: string | URL;
|
||||||
|
|
@ -10,14 +24,43 @@ interface Props {
|
||||||
|
|
||||||
const { target, locale = getLocaleFromUrl(Astro.url) ?? DEFAULT_LOCALE } = Astro.props;
|
const { target, locale = getLocaleFromUrl(Astro.url) ?? DEFAULT_LOCALE } = Astro.props;
|
||||||
|
|
||||||
const all = await getMentionsFor(target);
|
async function fetchMentions(target: string): Promise<WMEntry[]> {
|
||||||
const { likes, reposts, replies, mentions } = groupMentions(all);
|
const token = import.meta.env.WEBMENTION_TOKEN;
|
||||||
|
if (!token) return [];
|
||||||
|
const withSlash = target.endsWith('/') ? target : `${target}/`;
|
||||||
|
const withoutSlash = target.replace(/\/+$/, '');
|
||||||
|
const fetchOne = async (t: string) => {
|
||||||
|
const url = new URL('https://webmention.io/api/mentions.jf2');
|
||||||
|
url.searchParams.set('target', t);
|
||||||
|
url.searchParams.set('token', token);
|
||||||
|
url.searchParams.set('per-page', '100');
|
||||||
|
const res = await fetch(url);
|
||||||
|
if (!res.ok) return [] as WMEntry[];
|
||||||
|
const json = (await res.json()) as { children?: WMEntry[] };
|
||||||
|
return json.children ?? [];
|
||||||
|
};
|
||||||
|
const [a, b] = await Promise.all([fetchOne(withSlash), fetchOne(withoutSlash)]);
|
||||||
|
const seen = new Set<number>();
|
||||||
|
const merged: WMEntry[] = [];
|
||||||
|
for (const m of [...a, ...b]) {
|
||||||
|
const id = m['wm-id'];
|
||||||
|
if (id == null || seen.has(id)) continue;
|
||||||
|
seen.add(id);
|
||||||
|
merged.push(m);
|
||||||
|
}
|
||||||
|
return merged;
|
||||||
|
}
|
||||||
|
|
||||||
const facepile = [...likes, ...reposts];
|
const targetStr = target.toString();
|
||||||
|
const all = await fetchMentions(targetStr);
|
||||||
|
|
||||||
console.log(
|
const likes = all.filter((m) => m['wm-property'] === 'like-of');
|
||||||
`[webmentions component] target=${target.toString()} all=${all.length} likes=${likes.length} reposts=${reposts.length} replies=${replies.length} mentions=${mentions.length} facepile=${facepile.length}`,
|
const reposts = all.filter((m) => m['wm-property'] === 'repost-of');
|
||||||
|
const replies = all.filter((m) => m['wm-property'] === 'in-reply-to');
|
||||||
|
const mentions = all.filter(
|
||||||
|
(m) => !['like-of', 'repost-of', 'in-reply-to', 'bookmark-of'].includes(m['wm-property'] ?? ''),
|
||||||
);
|
);
|
||||||
|
const facepile = [...likes, ...reposts];
|
||||||
|
|
||||||
function authorInitial(m: WMEntry) {
|
function authorInitial(m: WMEntry) {
|
||||||
return m.author?.name?.trim()?.[0]?.toUpperCase() ?? '?';
|
return m.author?.name?.trim()?.[0]?.toUpperCase() ?? '?';
|
||||||
|
|
@ -34,13 +77,9 @@ function formatDate(iso?: string) {
|
||||||
}
|
}
|
||||||
|
|
||||||
const hasAny = facepile.length > 0 || replies.length > 0 || mentions.length > 0;
|
const hasAny = facepile.length > 0 || replies.length > 0 || mentions.length > 0;
|
||||||
|
|
||||||
console.log(`[webmentions component] hasAny=${hasAny}`);
|
|
||||||
---
|
---
|
||||||
|
|
||||||
<!-- DEBUG MARKER START -->
|
<div data-webmentions-debug data-target={targetStr} data-all={all.length} data-facepile={facepile.length} data-hasany={String(hasAny)} hidden></div>
|
||||||
<div>DEBUG: hasAny={hasAny ? 'true' : 'false'} facepile={facepile.length} likes={likes.length}</div>
|
|
||||||
<!-- DEBUG MARKER END -->
|
|
||||||
|
|
||||||
{
|
{
|
||||||
hasAny && (
|
hasAny && (
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue