rsshub
Version:
Make RSS Great Again!
92 lines (90 loc) • 3.25 kB
JavaScript
import "./esm-shims-CzJ_djXG.mjs";
import "./config-C37vj7VH.mjs";
import { t as ViewType } from "./types-D84BRIt4.mjs";
import "./dist-BInvbO1W.mjs";
import "./logger-Czu8UMNd.mjs";
import { t as ofetch_default } from "./ofetch-BIyrKU3Y.mjs";
import { parse } from "tldts";
//#region lib/routes/follow/profile.ts
const route = {
name: "User subscriptions",
categories: ["social-media"],
path: "/profile/:uid",
example: "/follow/profile/41279032429549568",
parameters: { uid: "User ID or user handle" },
radar: [{
source: ["app.follow.is/profile/:uid"],
target: "/profile/:uid"
}],
handler,
maintainers: [
"KarasuShin",
"DIYgod",
"DFobain"
],
features: { supportRadar: true },
view: ViewType.Notifications
};
const isList = (subscription) => "lists" in subscription;
const isInbox = (subscription) => "inboxId" in subscription;
const isFeed = (subscription) => "feeds" in subscription;
async function handler(ctx) {
const handleOrId = ctx.req.param("uid");
const host = "https://api.follow.is";
const handle = isBizId(handleOrId || "") ? handleOrId : handleOrId.startsWith("@") ? handleOrId.slice(1) : handleOrId;
const searchParams = new URLSearchParams({ handle });
if (isBizId(handle || "")) searchParams.append("id", handle);
const profile = await ofetch_default(`${host}/profiles?${searchParams.toString()}`);
const subscriptions = await ofetch_default(`${host}/subscriptions?userId=${profile.data.id}`);
return {
title: `${profile.data.name}'s subscriptions`,
item: subscriptions.data.filter((i) => !isInbox(i) && !(isFeed(i) && !!i.feeds.errorAt)).map((subscription) => {
if (isList(subscription)) return {
title: subscription.lists.title,
description: subscription.lists.description,
link: `https://app.follow.is/list/${subscription.listId}`,
image: subscription.lists.image
};
return {
title: subscription.feeds.title,
description: subscription.feeds.description,
link: `https://app.follow.is/feed/${subscription.feedId}`,
image: getUrlIcon(subscription.feeds.siteUrl).src,
category: subscription.category ? [subscription.category] : void 0
};
}),
link: `https://app.follow.is/share/users/${handleOrId}`,
image: profile.data.image
};
}
const getUrlIcon = (url, fallback) => {
let src;
let fallbackUrl = "";
try {
const { host } = new URL(url);
const pureDomain = parse(host).domainWithoutSuffix;
fallbackUrl = `https://avatar.vercel.sh/${pureDomain}.svg?text=${pureDomain?.slice(0, 2).toUpperCase()}`;
src = `https://unavatar.follow.is/${host}?fallback=${fallback || false}`;
} catch {
const pureDomain = parse(url).domainWithoutSuffix;
src = `https://avatar.vercel.sh/${pureDomain}.svg?text=${pureDomain?.slice(0, 2).toUpperCase()}`;
}
return {
src,
fallbackUrl
};
};
const EPOCH = 1712546615000n;
const MAX_TIMESTAMP_BITS = 41n;
const isBizId = (id) => {
if (!id || !/^\d{13,19}$/.test(id)) return false;
const snowflake = BigInt(id);
const timestamp = (snowflake >> 63n - MAX_TIMESTAMP_BITS) + EPOCH;
const date = new Date(Number(timestamp));
if (date.getFullYear() >= 2024 && date.getFullYear() <= 2050) {
if (snowflake <= (1n << 63n) - 1n) return true;
}
return false;
};
//#endregion
export { isBizId, route };