✨ addeds embeds for profiles
This commit is contained in:
parent
c90a4c141e
commit
5b5e21e614
9 changed files with 1006 additions and 896 deletions
3
.vscode/settings.json
vendored
3
.vscode/settings.json
vendored
|
|
@ -4,5 +4,6 @@
|
||||||
"editor.codeActionsOnSave": {
|
"editor.codeActionsOnSave": {
|
||||||
"source.fixAll": "explicit",
|
"source.fixAll": "explicit",
|
||||||
"source.organizeImports": "explicit"
|
"source.organizeImports": "explicit"
|
||||||
}
|
},
|
||||||
|
"typescript.tsdk": "node_modules\\typescript\\lib"
|
||||||
}
|
}
|
||||||
|
|
|
||||||
893
.yarn/releases/yarn-4.1.1.cjs
vendored
893
.yarn/releases/yarn-4.1.1.cjs
vendored
File diff suppressed because one or more lines are too long
925
.yarn/releases/yarn-4.5.0.cjs
vendored
Normal file
925
.yarn/releases/yarn-4.5.0.cjs
vendored
Normal file
File diff suppressed because one or more lines are too long
|
|
@ -1 +1 @@
|
||||||
yarnPath: .yarn/releases/yarn-4.1.1.cjs
|
yarnPath: .yarn/releases/yarn-4.5.0.cjs
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"name": "fixbluesky",
|
"name": "fixbluesky",
|
||||||
"private": true,
|
"private": true,
|
||||||
"packageManager": "yarn@4.1.1",
|
"packageManager": "yarn@4.5.0",
|
||||||
"volta": {
|
"volta": {
|
||||||
"node": "21.7.3",
|
"node": "21.7.3",
|
||||||
"yarn": "4.1.1"
|
"yarn": "4.1.1"
|
||||||
|
|
|
||||||
31
src/components/Profile.tsx
Normal file
31
src/components/Profile.tsx
Normal file
|
|
@ -0,0 +1,31 @@
|
||||||
|
import { AppBskyActorDefs } from "@atproto/api";
|
||||||
|
|
||||||
|
import { OEmbedTypes } from "../routes/getOEmbed.ts";
|
||||||
|
import { Layout } from "./Layout.tsx";
|
||||||
|
|
||||||
|
interface ProfileProps {
|
||||||
|
profile: AppBskyActorDefs.ProfileViewDetailed;
|
||||||
|
url: string;
|
||||||
|
appDomain: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const Profile = ({ profile, url, appDomain }: ProfileProps) => (
|
||||||
|
<Layout url={url}>
|
||||||
|
<meta name="twitter:creator" content={`@${profile.handle}`} />
|
||||||
|
<meta property="og:description" content={profile.description ?? ""} />
|
||||||
|
<meta
|
||||||
|
property="og:title"
|
||||||
|
content={`${profile.displayName} (@${profile.handle})`}
|
||||||
|
/>
|
||||||
|
<meta property="og:image" content={profile.avatar} />
|
||||||
|
|
||||||
|
<link
|
||||||
|
type="application/json+oembed"
|
||||||
|
href={`https://${appDomain}/oembed?type=${OEmbedTypes.Profile}&follows=${
|
||||||
|
profile.followsCount
|
||||||
|
}&posts=${profile.postsCount}&avatar=${encodeURIComponent(
|
||||||
|
profile.avatar ?? ""
|
||||||
|
)}`}
|
||||||
|
/>
|
||||||
|
</Layout>
|
||||||
|
);
|
||||||
14
src/lib/fetchProfile.ts
Normal file
14
src/lib/fetchProfile.ts
Normal file
|
|
@ -0,0 +1,14 @@
|
||||||
|
import { BskyAgent } from "@atproto/api";
|
||||||
|
|
||||||
|
export interface fetchProfileOptions {
|
||||||
|
user: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function fetchProfile(
|
||||||
|
agent: BskyAgent,
|
||||||
|
{ user }: fetchProfileOptions
|
||||||
|
) {
|
||||||
|
return agent.getProfile({
|
||||||
|
actor: user,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
@ -5,7 +5,9 @@ import { serve } from "@hono/node-server";
|
||||||
import { Hono } from "hono";
|
import { Hono } from "hono";
|
||||||
import { HTTPException } from "hono/http-exception";
|
import { HTTPException } from "hono/http-exception";
|
||||||
import { Redis } from "ioredis";
|
import { Redis } from "ioredis";
|
||||||
|
import { getOEmbed } from "./routes/getOEmbed.ts";
|
||||||
import { getPost } from "./routes/getPost.tsx";
|
import { getPost } from "./routes/getPost.tsx";
|
||||||
|
import { getProfile } from "./routes/getProfile.tsx";
|
||||||
|
|
||||||
// biome-ignore lint/style/noNonNullAssertion: check is ran at app start
|
// biome-ignore lint/style/noNonNullAssertion: check is ran at app start
|
||||||
const redis = new Redis(6379, process.env.REDIS_HOSTNAME!);
|
const redis = new Redis(6379, process.env.REDIS_HOSTNAME!);
|
||||||
|
|
@ -58,6 +60,11 @@ app.use("*", async (c, next) => {
|
||||||
app.get("/profile/:user/post/:post", getPost);
|
app.get("/profile/:user/post/:post", getPost);
|
||||||
app.get("/https://bsky.app/profile/:user/post/:post", getPost);
|
app.get("/https://bsky.app/profile/:user/post/:post", getPost);
|
||||||
|
|
||||||
|
app.get("/profile/:user", getProfile);
|
||||||
|
app.get("/https://bsky.app/profile/:user", getProfile);
|
||||||
|
|
||||||
|
app.get("/oembed", getOEmbed);
|
||||||
|
|
||||||
serve(
|
serve(
|
||||||
{
|
{
|
||||||
...app,
|
...app,
|
||||||
|
|
|
||||||
25
src/routes/getProfile.tsx
Normal file
25
src/routes/getProfile.tsx
Normal file
|
|
@ -0,0 +1,25 @@
|
||||||
|
import { Handler } from "hono";
|
||||||
|
import { HTTPException } from "hono/http-exception";
|
||||||
|
import { Profile } from "../components/Profile.tsx";
|
||||||
|
import { fetchProfile } from "../lib/fetchProfile.ts";
|
||||||
|
|
||||||
|
export const getProfile: Handler<
|
||||||
|
HonoEnv,
|
||||||
|
"/profile/:user" | "/https://bsky.app/profile/:user"
|
||||||
|
> = async (c) => {
|
||||||
|
const { user } = c.req.param();
|
||||||
|
const agent = c.get("Agent");
|
||||||
|
const { data, success } = await fetchProfile(agent, { user });
|
||||||
|
if (!success) {
|
||||||
|
throw new HTTPException(500, {
|
||||||
|
message: "Failed to fetch the profile!",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return c.html(
|
||||||
|
<Profile
|
||||||
|
profile={data}
|
||||||
|
url={c.req.path}
|
||||||
|
appDomain={process.env.FIXBLUESKY_APP_DOMAIN ?? "bsyy.app"}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
||||||
Loading…
Add table
Add a link
Reference in a new issue