tangled
alpha
login
or
join now
t1c.dev
/
rocksky
forked from
rocksky.app/rocksky
2
fork
atom
A decentralized music tracking and discovery platform built on AT Protocol 🎵
2
fork
atom
overview
issues
pulls
pipelines
fix: avoid duplicate scrobbles
tsiry-sandratraina.com
5 months ago
9f97a080
74e28d4b
+52
-54
1 changed file
expand all
collapse all
unified
split
apps
api
src
nowplaying
nowplaying.service.ts
+52
-54
apps/api/src/nowplaying/nowplaying.service.ts
···
13
13
14
14
export async function putArtistRecord(
15
15
track: Track,
16
16
-
agent: Agent,
16
16
+
agent: Agent
17
17
): Promise<string | null> {
18
18
const rkey = TID.nextStr();
19
19
const record: {
···
54
54
55
55
export async function putAlbumRecord(
56
56
track: Track,
57
57
-
agent: Agent,
57
57
+
agent: Agent
58
58
): Promise<string | null> {
59
59
const rkey = TID.nextStr();
60
60
···
94
94
95
95
export async function putSongRecord(
96
96
track: Track,
97
97
-
agent: Agent,
97
97
+
agent: Agent
98
98
): Promise<string | null> {
99
99
const rkey = TID.nextStr();
100
100
···
146
146
147
147
async function putScrobbleRecord(
148
148
track: Track,
149
149
-
agent: Agent,
149
149
+
agent: Agent
150
150
): Promise<string | null> {
151
151
const rkey = TID.nextStr();
152
152
···
308
308
ctx: Context,
309
309
track: Track,
310
310
agent: Agent,
311
311
-
userDid: string,
311
311
+
userDid: string
312
312
): Promise<void> {
313
313
// check if scrobble already exists (user did + timestamp)
314
314
-
const scrobbleTime = dayjs.unix(track.timestamp);
315
315
-
if (track.timestamp) {
316
316
-
const existingScrobble = await ctx.client.db.scrobbles
317
317
-
.filter("user_id.did", equals(userDid))
318
318
-
.filter("track_id.title", equals(track.title))
319
319
-
.filter("track_id.artist", equals(track.artist))
320
320
-
.filter({
321
321
-
$any: [
322
322
-
{
323
323
-
timestamp: {
324
324
-
$ge: scrobbleTime.subtract(5, "seconds").toISOString(),
325
325
-
},
314
314
+
const scrobbleTime = dayjs.unix(track.timestamp || dayjs().unix());
315
315
+
const existingScrobble = await ctx.client.db.scrobbles
316
316
+
.filter("user_id.did", equals(userDid))
317
317
+
.filter("track_id.title", equals(track.title))
318
318
+
.filter("track_id.artist", equals(track.artist))
319
319
+
.filter({
320
320
+
$any: [
321
321
+
{
322
322
+
timestamp: {
323
323
+
$ge: scrobbleTime.subtract(10, "seconds").toISOString(),
326
324
},
327
327
-
{ timestamp: { $le: scrobbleTime.add(5, "seconds").toISOString() } },
328
328
-
],
329
329
-
})
330
330
-
.getFirst();
325
325
+
},
326
326
+
{ timestamp: { $le: scrobbleTime.add(10, "seconds").toISOString() } },
327
327
+
],
328
328
+
})
329
329
+
.getFirst();
331
330
332
332
-
if (existingScrobble) {
333
333
-
console.log(
334
334
-
`Scrobble already exists for ${chalk.cyan(track.title)} at ${chalk.cyan(
335
335
-
dayjs.unix(track.timestamp).format("YYYY-MM-DD HH:mm:ss"),
336
336
-
)}`,
337
337
-
);
338
338
-
return;
339
339
-
}
331
331
+
if (existingScrobble) {
332
332
+
console.log(
333
333
+
`Scrobble already exists for ${chalk.cyan(track.title)} at ${chalk.cyan(
334
334
+
dayjs.unix(track.timestamp).format("YYYY-MM-DD HH:mm:ss")
335
335
+
)}`
336
336
+
);
337
337
+
return;
340
338
}
341
339
342
340
let existingTrack = await ctx.client.db.tracks
···
345
343
equals(
346
344
createHash("sha256")
347
345
.update(
348
348
-
`${track.title} - ${track.artist} - ${track.album}`.toLowerCase(),
346
346
+
`${track.title} - ${track.artist} - ${track.album}`.toLowerCase()
349
347
)
350
350
-
.digest("hex"),
351
351
-
),
348
348
+
.digest("hex")
349
349
+
)
352
350
)
353
351
.getFirst();
354
352
···
359
357
equals(
360
358
createHash("sha256")
361
359
.update(`${track.album} - ${track.albumArtist}`.toLowerCase())
362
362
-
.digest("hex"),
363
363
-
),
360
360
+
.digest("hex")
361
361
+
)
364
362
)
365
363
.getFirst();
366
364
if (album) {
···
377
375
equals(
378
376
createHash("sha256")
379
377
.update(track.albumArtist.toLowerCase())
380
380
-
.digest("hex"),
381
381
-
),
378
378
+
.digest("hex")
379
379
+
)
382
380
)
383
381
.getFirst();
384
382
if (artist) {
···
405
403
equals(
406
404
createHash("sha256")
407
405
.update(`${track.album} - ${track.albumArtist}`.toLowerCase())
408
408
-
.digest("hex"),
409
409
-
),
406
406
+
.digest("hex")
407
407
+
)
410
408
)
411
409
.getFirst();
412
410
···
419
417
equals(
420
418
createHash("sha256")
421
419
.update(
422
422
-
`${track.title} - ${track.artist} - ${track.album}`.toLowerCase(),
420
420
+
`${track.title} - ${track.artist} - ${track.album}`.toLowerCase()
423
421
)
424
424
-
.digest("hex"),
425
425
-
),
422
422
+
.digest("hex")
423
423
+
)
426
424
)
427
425
.getFirst();
428
426
await new Promise((resolve) => setTimeout(resolve, 1000));
···
435
433
436
434
if (existingTrack) {
437
435
console.log(
438
438
-
`Song found: ${chalk.cyan(existingTrack.xata_id)} - ${track.title}, after ${chalk.magenta(tries)} tries`,
436
436
+
`Song found: ${chalk.cyan(existingTrack.xata_id)} - ${track.title}, after ${chalk.magenta(tries)} tries`
439
437
);
440
438
}
441
439
···
485
483
equals(
486
484
createHash("sha256")
487
485
.update(
488
488
-
`${track.title} - ${track.artist} - ${track.album}`.toLowerCase(),
486
486
+
`${track.title} - ${track.artist} - ${track.album}`.toLowerCase()
489
487
)
490
490
-
.digest("hex"),
491
491
-
),
488
488
+
.digest("hex")
489
489
+
)
492
490
)
493
491
.getFirst();
494
492
···
498
496
tries < 30
499
497
) {
500
498
console.log(
501
501
-
`Artist uri not ready, trying again: ${chalk.magenta(tries + 1)}`,
499
499
+
`Artist uri not ready, trying again: ${chalk.magenta(tries + 1)}`
502
500
);
503
501
existingTrack = await ctx.client.db.tracks
504
502
.filter(
···
506
504
equals(
507
505
createHash("sha256")
508
506
.update(
509
509
-
`${track.title} - ${track.artist} - ${track.album}`.toLowerCase(),
507
507
+
`${track.title} - ${track.artist} - ${track.album}`.toLowerCase()
510
508
)
511
511
-
.digest("hex"),
512
512
-
),
509
509
+
.digest("hex")
510
510
+
)
513
511
)
514
512
.getFirst();
515
513
···
521
519
equals(
522
520
createHash("sha256")
523
521
.update(track.albumArtist.toLowerCase())
524
524
-
.digest("hex"),
525
525
-
),
522
522
+
.digest("hex")
523
523
+
)
526
524
)
527
525
.getFirst();
528
526
if (artist) {
···
541
539
equals(
542
540
createHash("sha256")
543
541
.update(`${track.album} - ${track.albumArtist}`.toLowerCase())
544
544
-
.digest("hex"),
545
545
-
),
542
542
+
.digest("hex")
543
543
+
)
546
544
)
547
545
.getFirst();
548
546
if (album) {
···
569
567
570
568
if (existingTrack?.artist_uri) {
571
569
console.log(
572
572
-
`Artist uri ready: ${chalk.cyan(existingTrack.xata_id)} - ${track.title}, after ${chalk.magenta(tries)} tries`,
570
570
+
`Artist uri ready: ${chalk.cyan(existingTrack.xata_id)} - ${track.title}, after ${chalk.magenta(tries)} tries`
573
571
);
574
572
}
575
573