A decentralized music tracking and discovery platform built on AT Protocol 馃幍
at feat/like-scrobble 120 lines 2.7 kB view raw
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;