mirror of
https://github.com/FoxxMD/multi-scrobbler.git
synced 2026-07-09 17:28:28 +00:00
feat(client): Implement createdAt dates for scrobble actions
This commit is contained in:
parent
3d6e86f258
commit
e6f4a1dbd2
3 changed files with 29 additions and 16 deletions
|
|
@ -19,7 +19,8 @@ import {
|
|||
CLIENT_DEAD_QUEUE,
|
||||
PlayOriginal,
|
||||
PlayLifecycle,
|
||||
SourcePlayerJson
|
||||
SourcePlayerJson,
|
||||
QUEUE_STATUS_COMPLETED
|
||||
} from "../../core/Atomic.js";
|
||||
import { artistNamesToCredits, buildTrackString, capitalize, truncateStringToLength } from "../../core/StringUtils.js";
|
||||
import AbstractComponent from "../common/AbstractComponent.js";
|
||||
|
|
@ -932,6 +933,7 @@ export default abstract class AbstractScrobbleClient extends AbstractComponent i
|
|||
...scrobble,
|
||||
payload: result.payload,
|
||||
warnings: result.warnings,
|
||||
createdAt: dayjs(),
|
||||
response: result.response,
|
||||
mergedScrobble: result.mergedScrobble !== undefined ? statefulInvariantTransform(result.mergedScrobble) : undefined
|
||||
}
|
||||
|
|
@ -1145,7 +1147,8 @@ export default abstract class AbstractScrobbleClient extends AbstractComponent i
|
|||
const { summary, ...matchResult } = await this.existingScrobble(currQueuedPlay.play, historicalPlays);
|
||||
currQueuedPlay.play.scrobble = {
|
||||
...(currQueuedPlay.play.scrobble ?? {}),
|
||||
match: matchResult
|
||||
match: matchResult,
|
||||
createdAt: dayjs()
|
||||
}
|
||||
signal.throwIfAborted();
|
||||
if (!matchResult.match) {
|
||||
|
|
@ -1158,6 +1161,7 @@ export default abstract class AbstractScrobbleClient extends AbstractComponent i
|
|||
//handledShiftedPlay = true;
|
||||
} catch (e) {
|
||||
currQueuedPlay.play.scrobble = {
|
||||
createdAt: dayjs()
|
||||
};
|
||||
|
||||
const submitError = findCauseByReference(e, ScrobbleSubmitError);
|
||||
|
|
@ -1210,7 +1214,7 @@ export default abstract class AbstractScrobbleClient extends AbstractComponent i
|
|||
queueState.error = queueError;
|
||||
await this.playRepo.updateById(currQueuedPlay.id, {state: 'failed', error: queueError, play: currQueuedPlay.play});
|
||||
currQueuedPlay.state = 'failed';
|
||||
currQueuedPlay.error = queueError;
|
||||
//currQueuedPlay.error = queueError;
|
||||
} else {
|
||||
await this.queueRepo.updateById(queueState.id, {queueStatus: 'completed'});
|
||||
await this.playRepo.updateById(currQueuedPlay.id, {state: successState ?? 'scrobbled', play: currQueuedPlay.play});
|
||||
|
|
@ -1314,15 +1318,14 @@ export default abstract class AbstractScrobbleClient extends AbstractComponent i
|
|||
// return [false];
|
||||
// }
|
||||
|
||||
let deadQueueState: QueueStateSelect;
|
||||
let deadScrobble: PlaySelectWithQueueStates = await this.playRepo.findByUid(uid, {hydrate: ['asPlay']});
|
||||
const deadScrobble: PlaySelectWithQueueStates = await this.playRepo.findByUid(uid, {hydrate: ['asPlay']});
|
||||
if(deadScrobble === undefined) {
|
||||
throw new Error(`Play ${uid} does not exist for ${this.name}`);
|
||||
}
|
||||
if(deadScrobble.state === 'scrobbled') {
|
||||
throw new Error(`Play ${uid} is already scrobbled.`);
|
||||
}
|
||||
deadQueueState = deadScrobble.queueStates.find(x => x.queueName === CLIENT_DEAD_QUEUE);
|
||||
const deadQueueState: QueueStateSelect = deadScrobble.queueStates.find(x => x.queueName === CLIENT_DEAD_QUEUE);
|
||||
if(deadQueueState === undefined) {
|
||||
throw new Error(`Play ${uid} is not currently queued in dead letter.`);
|
||||
}
|
||||
|
|
@ -1352,7 +1355,7 @@ export default abstract class AbstractScrobbleClient extends AbstractComponent i
|
|||
}
|
||||
|
||||
this.queueRepo.updateById(deadQueueState.id, {retries: deadQueueState.retries + 1, error: e, updatedAt: dayjs(), queueStatus: 'failed'});
|
||||
this.playRepo.updateById(deadScrobble.id, {error: e});
|
||||
//this.playRepo.updateById(deadScrobble.id, {error: e});
|
||||
// deadScrobble.retries++;
|
||||
// deadScrobble.error = messageWithCauses(e);
|
||||
// deadScrobble.lastRetry = dayjs();
|
||||
|
|
@ -1365,18 +1368,23 @@ export default abstract class AbstractScrobbleClient extends AbstractComponent i
|
|||
const {summary, ...matchResult} = await this.existingScrobble(deadScrobble.play, historicalPlays);
|
||||
deadScrobble.play.scrobble = {
|
||||
...(deadScrobble.play.scrobble ?? {}),
|
||||
match: matchResult
|
||||
match: matchResult,
|
||||
createdAt: dayjs()
|
||||
}
|
||||
if(!matchResult.match) {
|
||||
const transformedScrobble = await this.transformPlay(deadScrobble.play, TRANSFORM_HOOK.postCompare);
|
||||
signal?.throwIfAborted();
|
||||
try {
|
||||
const scrobbledPlay = await this.scrobble(transformedScrobble);
|
||||
deadScrobble.play = scrobbledPlay;
|
||||
await this.addScrobbledTrack(scrobbledPlay);
|
||||
this.playRepo.updateById(deadScrobble.id, {play: deadScrobble.play});
|
||||
this.queueRepo.updateById(deadQueueState.id, {error: null, updatedAt: dayjs(), queueStatus: QUEUE_STATUS_COMPLETED});
|
||||
this.removeDeadLetterScrobble(deadScrobble, 'scrobbled', true);
|
||||
} catch (e) {
|
||||
deadScrobble.play.scrobble = {
|
||||
...(deadScrobble.play.scrobble ?? {})
|
||||
...(deadScrobble.play.scrobble ?? {}),
|
||||
createdAt: dayjs()
|
||||
}
|
||||
const submitError = findCauseByReference(e, ScrobbleSubmitError);
|
||||
if(submitError !== undefined) {
|
||||
|
|
@ -1389,7 +1397,7 @@ export default abstract class AbstractScrobbleClient extends AbstractComponent i
|
|||
}
|
||||
|
||||
this.queueRepo.updateById(deadQueueState.id, {retries: deadQueueState.retries + 1, error: e, updatedAt: dayjs(), queueStatus: 'failed'});
|
||||
this.playRepo.updateById(deadScrobble.id, {error: e});
|
||||
this.playRepo.updateById(deadScrobble.id, {play: deadScrobble.play});
|
||||
// deadScrobble.retries++;
|
||||
// deadScrobble.error = messageWithCauses(e);
|
||||
// deadScrobble.lastRetry = dayjs();
|
||||
|
|
@ -1399,6 +1407,7 @@ export default abstract class AbstractScrobbleClient extends AbstractComponent i
|
|||
return [false, deadScrobble];
|
||||
}
|
||||
} else {
|
||||
this.playRepo.updateById(deadScrobble.id, {play: deadScrobble.play});
|
||||
this.deadLogger.verbose(`Looks like ${buildTrackString(deadScrobble.play)} was already scrobbled!\n${summary}`);
|
||||
this.removeDeadLetterScrobble(deadScrobble, 'duped', true);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -313,6 +313,7 @@ export interface ScrobbleResult<D extends DateLike = Dayjs> {
|
|||
error?: Error | ErrorObject
|
||||
response?: ScrobbleResponse
|
||||
mergedScrobble?: AmbPlayObjectMinimal<D>
|
||||
createdAt?: D
|
||||
}
|
||||
|
||||
export interface PlayLifecycle<D extends DateLike = Dayjs> {
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
import { Traverse, TraverseContext } from 'neotraverse/modern';
|
||||
import { Traverse } from 'neotraverse/modern';
|
||||
import { faker } from '@faker-js/faker';
|
||||
import { AmbPlayObject, DateLike, LifecycleInput, LifecycleStep, ObjectPlayData, PLAY_STATES, PlayMeta, PlayObject, PlayOriginal, PlayState, ScrobbleResult } from '../../Atomic.js';
|
||||
import { MarkOptional } from 'ts-essentials';
|
||||
import { generateBrainz, generateMbid, generatePlay, GeneratePlayOpts, generatePlays } from '../../PlayTestUtils.js';
|
||||
import { statefulInvariantTransform } from '../../PlayUtils.js';
|
||||
import clone from 'clone';
|
||||
|
|
@ -52,7 +51,7 @@ export const generatePlayWithLifecycle = (opts: GeneratePlayWithLifecycleOptions
|
|||
//lplay.meta.lifecycle.original = lifecyclelessInvariantTransform(original);
|
||||
//lplay.meta.lifecycle.input = generateRandomObj();
|
||||
|
||||
let steps: LifecycleStep[] = [];
|
||||
const steps: LifecycleStep[] = [];
|
||||
let transformedPlay = clone(original);
|
||||
|
||||
if(preCompare !== undefined) {
|
||||
|
|
@ -115,7 +114,9 @@ export const playWithLifecycleScrobble = async (play: PlayObject, opts: Scrobble
|
|||
error = false,
|
||||
} = opts;
|
||||
|
||||
const scrobbleRes: ScrobbleResult = {};
|
||||
const scrobbleRes: ScrobbleResult = {
|
||||
createdAt: dayjs()
|
||||
};
|
||||
|
||||
const existingPlays = generatePlays(2);
|
||||
|
||||
|
|
@ -278,8 +279,10 @@ const generateRandomVal = (depth: number = 0, opt: RandomObjOptions = {}, typeId
|
|||
case 7:
|
||||
return generateRandomObj(depth + 1, opt);
|
||||
case 8:
|
||||
const typeId = faker.number.int({ min: 4, max: depth > (opt.maxDepth ?? 3) ? 6 : 7 });
|
||||
return faker.helpers.multiple(() => generateRandomVal(depth + 1, opt, typeId), { count: { min: 1, max: opt.maxObjSize ?? 7 } })
|
||||
{
|
||||
const typeId = faker.number.int({ min: 4, max: depth > (opt.maxDepth ?? 3) ? 6 : 7 });
|
||||
return faker.helpers.multiple(() => generateRandomVal(depth + 1, opt, typeId), { count: { min: 1, max: opt.maxObjSize ?? 7 } })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue