forked from
rocksky.app/rocksky
A decentralized music tracking and discovery platform built on AT Protocol 馃幍
1/**
2 * Welcome to Cloudflare Workers! This is your first worker.
3 *
4 * - Run `npm run dev` in your terminal to start a development server
5 * - Open a browser tab at http://localhost:8787/ to see your worker in action
6 * - Run `npm run deploy` to publish your worker
7 *
8 * Bind resources to your worker in `wrangler.json`. After adding bindings, a type definition for the
9 * `Env` object can be regenerated with `npm run cf-typegen`.
10 *
11 * Learn more at https://developers.cloudflare.com/workers/
12 */
13
14const metadata = {
15 redirect_uris: ['https://rocksky.app/oauth/callback'],
16 response_types: ['code'],
17 grant_types: ['authorization_code', 'refresh_token'],
18 scope: 'atproto transition:generic',
19 token_endpoint_auth_method: 'none',
20 application_type: 'web',
21 client_id: 'https://rocksky.app/client-metadata.json',
22 client_name: 'AT Protocol Express App',
23 client_uri: 'https://rocksky.app',
24 dpop_bound_access_tokens: true,
25};
26
27const jwks = {
28 keys: [
29 {
30 kty: 'EC',
31 use: 'sig',
32 alg: 'ES256',
33 kid: '2dfa3fd9-57b3-4738-ac27-9e6dadec13b7',
34 crv: 'P-256',
35 x: 'V_00KDnoEPsNqbt0y2Ke8v27Mv9WP70JylDUD5rvIek',
36 y: 'HAyjaQeA2DU6wjZO0ggTadUS6ij1rmiYTxzmWeBKfRc',
37 },
38 {
39 kty: 'EC',
40 use: 'sig',
41 alg: 'ES256',
42 kid: '5e816ff2-6bff-4177-b1c0-67ad3cd3e7cd',
43 crv: 'P-256',
44 x: 'YwEY5NsoYQVB_G7xPYMl9sUtxRbcPFNffnZcTS5nbPQ',
45 y: '5n5mybPvISyYAnRv1Ii1geqKfXv2GA8p9Xemwx2a8CM',
46 },
47 {
48 kty: 'EC',
49 use: 'sig',
50 kid: 'a1067a48-a54a-43a0-9758-4d55b51fdd8b',
51 crv: 'P-256',
52 x: 'yq17Nd2DGcjP1i9I0NN3RBmgSbLQUZOtG6ec5GaqzmU',
53 y: 'ieIU9mcfaZwAW5b3WgJkIRgddymG_ckcZ0n1XjbEIvc',
54 },
55 ],
56};
57
58export default {
59 async fetch(request, env, ctx): Promise<Response> {
60 const url = new URL(request.url);
61 let redirectToApi = false;
62
63 const API_ROUTES = ['/login', '/profile', '/token', '/now-playing', '/ws'];
64
65 console.log('Request URL:', url.pathname, url.pathname === '/client-metadata.json');
66
67 if (url.pathname === '/client-metadata.json') {
68 return Response.json(metadata);
69 }
70
71 if (url.pathname === '/jwks.json') {
72 return Response.json(jwks);
73 }
74
75 if (
76 API_ROUTES.includes(url.pathname) ||
77 url.pathname.startsWith('/oauth/callback') ||
78 url.pathname.startsWith('/users') ||
79 url.pathname.startsWith('/albums') ||
80 url.pathname.startsWith('/artists') ||
81 url.pathname.startsWith('/tracks') ||
82 url.pathname.startsWith('/scrobbles') ||
83 url.pathname.startsWith('/likes') ||
84 url.pathname.startsWith('/spotify') ||
85 url.pathname.startsWith('/dropbox/oauth/callback') ||
86 url.pathname.startsWith('/googledrive/oauth/callback') ||
87 url.pathname.startsWith('/dropbox/files') ||
88 url.pathname.startsWith('/dropbox/file') ||
89 url.pathname.startsWith('/googledrive/files') ||
90 url.pathname.startsWith('/dropbox/login') ||
91 url.pathname.startsWith('/googledrive/login') ||
92 url.pathname.startsWith('/dropbox/join') ||
93 url.pathname.startsWith('/googledrive/join') ||
94 url.pathname.startsWith('/search') ||
95 url.pathname.startsWith('/public/scrobbles')
96 ) {
97 redirectToApi = true;
98 }
99
100 if (redirectToApi) {
101 const proxyUrl = new URL(request.url);
102 proxyUrl.host = 'api.rocksky.app';
103 proxyUrl.hostname = 'api.rocksky.app';
104 return fetch(proxyUrl, request) as any;
105 }
106
107 // check header if from mobile device, android or ios
108 const userAgent = request.headers.get('user-agent');
109 const mobileRegex = /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i;
110 const isMobile = mobileRegex.test(userAgent!);
111
112 if (isMobile) {
113 const mobileUrl = new URL(request.url);
114 mobileUrl.host = 'm.rocksky.app';
115 mobileUrl.hostname = 'm.rocksky.app';
116 return fetch(mobileUrl, request);
117 }
118
119 const proxyUrl = new URL(request.url);
120 proxyUrl.host = 'rocksky.pages.dev';
121 proxyUrl.hostname = 'rocksky.pages.dev';
122 return fetch(proxyUrl, request) as any;
123 },
124} satisfies ExportedHandler<Env>;