A decentralized music tracking and discovery platform built on AT Protocol 🎵 rocksky.app
spotify atproto lastfm musicbrainz scrobbling listenbrainz

[api] refresh user sessions

+56
+28
rockskyapi/rocksky-auth/src/bsky/app.ts
··· 1 1 import { BlobRef } from "@atproto/lexicon"; 2 2 import { isValidHandle } from "@atproto/syntax"; 3 3 import { equals } from "@xata.io/client"; 4 + import chalk from "chalk"; 4 5 import { ctx } from "context"; 5 6 import { desc, eq } from "drizzle-orm"; 6 7 import { Hono } from "hono"; ··· 70 71 cli = ctx.kv.get(`cli:${handle}`); 71 72 ctx.kv.delete(`cli:${handle}`); 72 73 74 + await fetch(`http://localhost:8000/refresh/${did}`, { 75 + method: "POST", 76 + headers: { 77 + "Content-Type": "application/json", 78 + }, 79 + body: JSON.stringify({}), 80 + }); 81 + 73 82 const token = jwt.sign( 74 83 { did, exp: Math.floor(Date.now() / 1000) + 60 * 60 * 24 * 7 }, 75 84 env.JWT_SECRET ··· 94 103 } 95 104 96 105 return c.redirect(`${env.FRONTEND_URL}?did=${did}&cli=${cli}`); 106 + }); 107 + 108 + app.post("/refresh/:did", async (c) => { 109 + const cache = await ctx.redis.get(`refresh:${c.req.param("did")}`); 110 + if (cache) { 111 + return c.text(cache); 112 + } 113 + 114 + const did = c.req.param("did"); 115 + setInterval( 116 + () => { 117 + createAgent(ctx.oauthClient, did).catch(() => {}); 118 + console.log(`Refreshing agent for ${chalk.greenBright(did)}`); 119 + }, 120 + // every 5 minutes 121 + 5 * 60 * 1000 122 + ); 123 + await ctx.redis.set(`refresh:${did}`, did); 124 + return c.text("ok"); 97 125 }); 98 126 99 127 app.get("/profile", async (c) => {
+3
rockskyapi/rocksky-auth/src/index.ts
··· 14 14 } from "lovedtracks/lovedtracks.service"; 15 15 import { scrobbleTrack } from "nowplaying/nowplaying.service"; 16 16 import { rateLimiter } from "ratelimiter"; 17 + import { refreshSessions } from "sessions"; 17 18 import subscribe from "subscribers"; 18 19 import { saveTrack } from "tracks/tracks.service"; 19 20 import { trackSchema } from "types/track"; ··· 31 32 import users from "./users/app"; 32 33 33 34 subscribe(ctx); 35 + 36 + refreshSessions(); 34 37 35 38 const app = new Hono(); 36 39 const { injectWebSocket, upgradeWebSocket } = createNodeWebSocket({ app });
+25
rockskyapi/rocksky-auth/src/sessions.ts
··· 1 + import chalk from "chalk"; 2 + import { ctx } from "context"; 3 + import { createAgent } from "lib/agent"; 4 + 5 + export async function refreshSessions() { 6 + const keys = await ctx.redis.keys("refresh:*"); 7 + return new Promise<void>((resolve) => { 8 + for (const key of keys) { 9 + const did = key.split(":")[1]; 10 + setTimeout(() => { 11 + setInterval( 12 + async () => { 13 + createAgent(ctx.oauthClient, did).catch(() => {}); 14 + console.log(`Refreshing agent for ${chalk.greenBright(did)}`); 15 + }, 16 + // every 5 minutes 17 + 5 * 60 * 1000 18 + ); 19 + }, 5 * 1000); 20 + } 21 + 22 + console.log(`Refreshed ${chalk.greenBright(keys.length)} sessions`); 23 + resolve(); 24 + }); 25 + }