mirror of
https://github.com/bookorbit/bookorbit.git
synced 2026-11-03 00:11:37 -06:00
fix(kobo): refuse a replacement with the bytes the device already has
A replacement byte-identical to the device's copy was never downloaded, so it stayed offered and every bookmark the device pushed was discarded. Keep the current delivery instead, and tell the user in the replacement panel that the device already has this copy. Ref #1786
This commit is contained in:
@@ -52,6 +52,9 @@ export class KoboDeliveryRepository {
|
||||
throw new ConflictException({ code: 'KOBO_REPLACEMENT_ALREADY_PENDING' });
|
||||
return existing;
|
||||
}
|
||||
// The device already holds these exact bytes. A replacement it never needs to download would stay
|
||||
// offered, and keep every bookmark it pushes from counting, so there is nothing to replace.
|
||||
if (replace && existing && !existing.options.replacement && existing.metadata.sha256 === values.metadata.sha256) return existing;
|
||||
if (existing) await tx.update(schema.koboDeviceDeliveries).set({ current: false }).where(eq(schema.koboDeviceDeliveries.id, existing.id));
|
||||
const [row] = await tx
|
||||
.insert(schema.koboDeviceDeliveries)
|
||||
|
||||
@@ -439,6 +439,21 @@ describe('Read-aloud delivery contracts (e2e)', { timeout: 180_000 }, () => {
|
||||
expect((await download()).rawPayload).toEqual(sourceBytes);
|
||||
});
|
||||
|
||||
it('keeps the current delivery instead of offering a replacement with the bytes the device already has', async () => {
|
||||
const device = (await request('POST', '/api/v1/kobo/devices', { name: 'Identical replacement' })).json();
|
||||
await request('PATCH', '/api/v1/kobo/settings', { readAloudDelivery: 'audioless_epub' });
|
||||
const base = `/api/v1/kobo/devices/${device.id}`;
|
||||
expect((await ctx.app.inject({ method: 'GET', url: `/api/v1/kobo/${device.token}/v1/books/${book.bookId}/download` })).statusCode).toBe(200);
|
||||
const delivered = (await request('GET', `${base}/books/${book.bookId}/delivery`)).json();
|
||||
|
||||
const prepared = await request('POST', `${base}/books/${book.bookId}/replacement`, { variant: 'audioless_epub' });
|
||||
|
||||
expect(prepared.statusCode).toBe(201);
|
||||
expect(prepared.json()).toMatchObject({ id: delivered.id, options: { replacement: false } });
|
||||
const rows = await ctx.db.query.koboDeviceDeliveries.findMany({ where: eq(schema.koboDeviceDeliveries.deviceId, device.id) });
|
||||
expect(rows).toHaveLength(1);
|
||||
});
|
||||
|
||||
describe('Storyteller progress-reset regressions over live HTTP', () => {
|
||||
let origin: string;
|
||||
const cfi = 'epubcfi(/6/2!/4/2/2/1:3)';
|
||||
|
||||
Reference in New Issue
Block a user