forked from
rocksky.app/rocksky
A decentralized music tracking and discovery platform built on AT Protocol 馃幍
1import { ctx } from "context";
2import { eq, or } from "drizzle-orm";
3import { Hono } from "hono";
4import jwt from "jsonwebtoken";
5import { env } from "lib/env";
6import users from "schema/users";
7import webscrobblers from "schema/webscrobblers";
8import { v4 as uuid } from "uuid";
9
10const app = new Hono();
11
12app.get("/", async (c) => {
13 const bearer = (c.req.header("authorization") || "").split(" ")[1]?.trim();
14
15 if (!bearer || bearer === "null") {
16 c.status(401);
17 return c.text("Unauthorized");
18 }
19
20 const { did } = jwt.verify(bearer, env.JWT_SECRET, {
21 ignoreExpiration: true,
22 });
23
24 const user = await ctx.db
25 .select()
26 .from(users)
27 .where(or(eq(users.did, did), eq(users.handle, did)))
28 .limit(1)
29 .then((rows) => rows[0]);
30
31 if (!user) {
32 c.status(401);
33 return c.text("Unauthorized");
34 }
35
36 const records = await ctx.db
37 .select()
38 .from(webscrobblers)
39 .leftJoin(users, eq(webscrobblers.userId, users.id))
40 .where(eq(users.did, did));
41
42 if (records.length === 0) {
43 const [record] = await ctx.db
44 .insert(webscrobblers)
45 .values({
46 uuid: uuid(),
47 userId: user.id,
48 name: "webscrobbler",
49 })
50 .returning();
51 return c.json(record);
52 }
53
54 return c.json(records[0].webscrobblers);
55});
56
57app.put("/:id", async (c) => {
58 const bearer = (c.req.header("authorization") || "").split(" ")[1]?.trim();
59 const id = c.req.param("id");
60
61 if (!bearer || bearer === "null") {
62 c.status(401);
63 return c.text("Unauthorized");
64 }
65
66 const { did } = jwt.verify(bearer, env.JWT_SECRET, {
67 ignoreExpiration: true,
68 });
69
70 const user = await ctx.db
71 .select()
72 .from(users)
73 .where(or(eq(users.did, did), eq(users.handle, did)))
74 .limit(1)
75 .then((rows) => rows[0]);
76
77 if (!user) {
78 c.status(401);
79 return c.text("Unauthorized");
80 }
81
82 if (
83 !id.match(/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/)
84 ) {
85 c.status(400);
86 return c.text("Invalid id");
87 }
88
89 const existing = await ctx.db
90 .select()
91 .from(webscrobblers)
92 .where(eq(webscrobblers.userId, user.id))
93 .limit(1)
94 .then((rows) => rows[0]);
95
96 if (existing) {
97 const [record] = await ctx.db
98 .update(webscrobblers)
99 .set({
100 uuid: id,
101 userId: user.id,
102 name: "webscrobbler",
103 })
104 .where(eq(webscrobblers.id, existing.id))
105 .returning();
106 return c.json(record);
107 } else {
108 const [record] = await ctx.db
109 .insert(webscrobblers)
110 .values({
111 uuid: id,
112 userId: user.id,
113 name: "webscrobbler",
114 })
115 .returning();
116 return c.json(record);
117 }
118});
119
120export default app;