tangled
alpha
login
or
join now
rocksky.app
/
rocksky
96
fork
atom
A decentralized music tracking and discovery platform built on AT Protocol 🎵
rocksky.app
spotify
atproto
lastfm
musicbrainz
scrobbling
listenbrainz
96
fork
atom
overview
issues
7
pulls
pipelines
Merge branch 'main' into feat/feed-generator
tsiry-sandratraina.com
2 months ago
df6c3f38
922075e3
+37
-15
4 changed files
expand all
collapse all
unified
split
apps
api
src
auth
client.ts
lib
env.ts
xrpc
app
rocksky
charts
getScrobblesChart.ts
feed
getNowPlayings.ts
+4
-2
apps/api/src/auth/client.ts
···
8
8
9
9
export const createClient = async (db: Database) => {
10
10
const publicUrl = env.PUBLIC_URL;
11
11
-
const url = publicUrl || `http://127.0.0.1:${env.PORT}`;
11
11
+
const url = publicUrl.includes("localhost")
12
12
+
? `http://127.0.0.1:${env.PORT}`
13
13
+
: publicUrl;
12
14
const enc = encodeURIComponent;
13
15
14
16
const redis = new Redis(env.REDIS_URL);
···
26
28
return new NodeOAuthClient({
27
29
clientMetadata: {
28
30
client_name: "Rocksky",
29
29
-
client_id: publicUrl
31
31
+
client_id: !publicUrl.includes("localhost")
30
32
? `${url}/oauth-client-metadata.json`
31
33
: `http://localhost?redirect_uri=${enc(
32
34
`${url}/oauth/callback`,
+1
-1
apps/api/src/lib/env.ts
···
10
10
}),
11
11
HOST: host({ devDefault: testOnly("localhost") }),
12
12
PORT: port({ devDefault: testOnly(8000) }),
13
13
-
PUBLIC_URL: str({}),
13
13
+
PUBLIC_URL: str({ devDefault: "http://localhost:8000" }),
14
14
DB_PATH: str({ devDefault: ":memory:" }),
15
15
KV_DB_PATH: str({ devDefault: ":memory:" }),
16
16
COOKIE_SECRET: str({ devDefault: "00000000000000000000000000000000" }),
+16
-6
apps/api/src/xrpc/app/rocksky/charts/getScrobblesChart.ts
···
1
1
import type { Context } from "context";
2
2
import { eq } from "drizzle-orm";
3
3
-
import { Effect, Match, pipe } from "effect";
3
3
+
import { Effect, Match, pipe, Cache, Duration } from "effect";
4
4
import type { Server } from "lexicon";
5
5
import type { ChartsView } from "lexicon/types/app/rocksky/charts/defs";
6
6
import type { QueryParams } from "lexicon/types/app/rocksky/charts/getScrobblesChart";
7
7
import tables from "schema";
8
8
9
9
export default function (server: Server, ctx: Context) {
10
10
+
const getScrobblesCache = Cache.make({
11
11
+
capacity: 100,
12
12
+
timeToLive: Duration.seconds(30),
13
13
+
lookup: (params: QueryParams) =>
14
14
+
pipe(
15
15
+
{ params, ctx },
16
16
+
retrieve,
17
17
+
Effect.flatMap(presentation),
18
18
+
Effect.retry({ times: 3 }),
19
19
+
Effect.timeout("10 seconds"),
20
20
+
),
21
21
+
});
22
22
+
10
23
const getScrobblesChart = (params) =>
11
24
pipe(
12
12
-
{ params, ctx },
13
13
-
retrieve,
14
14
-
Effect.flatMap(presentation),
15
15
-
Effect.retry({ times: 3 }),
16
16
-
Effect.timeout("10 seconds"),
25
25
+
getScrobblesCache,
26
26
+
Effect.flatMap((cache) => cache.get(params)),
17
27
Effect.catchAll((err) => {
18
28
console.error(err);
19
29
return Effect.succeed({ scrobbles: [] });
+16
-6
apps/api/src/xrpc/app/rocksky/feed/getNowPlayings.ts
···
1
1
import type { Context } from "context";
2
2
-
import { Effect, pipe } from "effect";
2
2
+
import { Effect, pipe, Cache, Duration } from "effect";
3
3
import type { Server } from "lexicon";
4
4
import type { NowPlayingView } from "lexicon/types/app/rocksky/feed/defs";
5
5
import type { QueryParams } from "lexicon/types/app/rocksky/feed/getNowPlayings";
6
6
import { deepCamelCaseKeys } from "lib";
7
7
8
8
export default function (server: Server, ctx: Context) {
9
9
+
const nowPlayingCache = Cache.make({
10
10
+
capacity: 100,
11
11
+
timeToLive: Duration.seconds(30),
12
12
+
lookup: (params: QueryParams) =>
13
13
+
pipe(
14
14
+
{ params, ctx },
15
15
+
retrieve,
16
16
+
Effect.flatMap(presentation),
17
17
+
Effect.retry({ times: 3 }),
18
18
+
Effect.timeout("10 seconds"),
19
19
+
),
20
20
+
});
21
21
+
9
22
const getNowPlayings = (params) =>
10
23
pipe(
11
11
-
{ params, ctx },
12
12
-
retrieve,
13
13
-
Effect.flatMap(presentation),
14
14
-
Effect.retry({ times: 3 }),
15
15
-
Effect.timeout("10 seconds"),
24
24
+
nowPlayingCache,
25
25
+
Effect.flatMap((cache) => cache.get(params)),
16
26
Effect.catchAll((err) => {
17
27
console.error(err);
18
28
return Effect.succeed({});