Compare commits
3 commits
c90a4c141e
...
59350d61f3
| Author | SHA1 | Date | |
|---|---|---|---|
| 59350d61f3 | |||
| eb97ade514 | |||
| 5b5e21e614 |
10 changed files with 1059 additions and 895 deletions
48
.forgejo/workflows/devel.yml
Normal file
48
.forgejo/workflows/devel.yml
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
name: Build Docker Image
|
||||
on:
|
||||
push:
|
||||
branches: [devel]
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
container:
|
||||
image: node:21-alpine
|
||||
steps:
|
||||
- name: Setup Node
|
||||
run: |
|
||||
apk add --no-cache libc6-compat
|
||||
apk update
|
||||
yarn set version canary
|
||||
yarn config set nodeLinker node-modules
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
- name: Run Node CI Stuff
|
||||
run: |
|
||||
yarn install --immutable
|
||||
yarn lint
|
||||
- name: Docker Metadata
|
||||
id: metadata
|
||||
uses: docker/metadata-action@v5
|
||||
with:
|
||||
images: git.thornbush.dev/rose/fixbluesky
|
||||
tags: |
|
||||
type=ref,event=branch
|
||||
type=sha,prefix=
|
||||
type=edge,branch=devel
|
||||
- name: Docker Buildx
|
||||
uses: https://code.forgejo.org/docker/setup-buildx-action@v3
|
||||
- name: Login to Docker Registry
|
||||
if: github.event_name != 'pull_request'
|
||||
uses: https://code.forgejo.org/docker/login-action@v3
|
||||
with:
|
||||
registry: git.thornbush.dev
|
||||
username: ${{github.actor}}
|
||||
password: ${{secrets.OAUTH_TOKEN}}
|
||||
- name: Build Image
|
||||
uses: https://code.forgejo.org/docker/build-push-action@v6
|
||||
with:
|
||||
context: .
|
||||
file: ./Dockerfile
|
||||
push: ${{ github.event_name != 'pull_request' }}
|
||||
tags: ${{ steps.metadata.outputs.tags }}
|
||||
labels: ${{ steps.metadata.outputs.labels }}
|
||||
4
.vscode/settings.json
vendored
4
.vscode/settings.json
vendored
|
|
@ -4,5 +4,9 @@
|
|||
"editor.codeActionsOnSave": {
|
||||
"source.fixAll": "explicit",
|
||||
"source.organizeImports": "explicit"
|
||||
},
|
||||
"typescript.tsdk": "node_modules\\typescript\\lib",
|
||||
"[typescript]": {
|
||||
"editor.defaultFormatter": "biomejs.biome"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
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",
|
||||
"private": true,
|
||||
"packageManager": "yarn@4.1.1",
|
||||
"packageManager": "yarn@4.5.0",
|
||||
"volta": {
|
||||
"node": "21.7.3",
|
||||
"yarn": "4.1.1"
|
||||
|
|
|
|||
34
src/components/Profile.tsx
Normal file
34
src/components/Profile.tsx
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
import type { 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 type { 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 { 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
25
src/routes/getProfile.tsx
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
import type { 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