v1 of FixBluesky #1

Merged
rose merged 32 commits from devel into main 2024-10-16 16:48:34 +00:00
9 changed files with 1006 additions and 896 deletions
Showing only changes of commit 5b5e21e614 - Show all commits

View file

@ -4,5 +4,6 @@
"editor.codeActionsOnSave": {
"source.fixAll": "explicit",
"source.organizeImports": "explicit"
}
},
"typescript.tsdk": "node_modules\\typescript\\lib"
}

File diff suppressed because one or more lines are too long

925
.yarn/releases/yarn-4.5.0.cjs vendored Normal file

File diff suppressed because one or more lines are too long

View file

@ -1 +1 @@
yarnPath: .yarn/releases/yarn-4.1.1.cjs
yarnPath: .yarn/releases/yarn-4.5.0.cjs

View file

@ -1,7 +1,7 @@
{
"name": "fixbluesky",
"private": true,
"packageManager": "yarn@4.1.1",
"packageManager": "yarn@4.5.0",
"volta": {
"node": "21.7.3",
"yarn": "4.1.1"

View 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
View 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,
});
}

View file

@ -5,7 +5,9 @@ import { serve } from "@hono/node-server";
import { Hono } from "hono";
import { HTTPException } from "hono/http-exception";
import { Redis } from "ioredis";
import { getOEmbed } from "./routes/getOEmbed.ts";
import { getPost } from "./routes/getPost.tsx";
import { getProfile } from "./routes/getProfile.tsx";
// biome-ignore lint/style/noNonNullAssertion: check is ran at app start
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("/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(
{
...app,

25
src/routes/getProfile.tsx Normal file
View 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"}
/>
);
};