feat: backfiller le catalogue existant, une parole/heure

This commit is contained in:
2026-07-05 01:07:31 +04:00
parent 26471d8b0e
commit e416f94061
3 changed files with 129 additions and 0 deletions
@@ -0,0 +1,75 @@
import {describe, it, expect, vi, afterEach} from 'vitest';
import {backfillBokanteMirror} from '../backfill-bokante-mirrors.js';
const bokanteMastodon = require('../bokante-mastodon.js');
function buildStrapi({paroles = []} = {}) {
const updateMany = vi.fn();
return {
db: {
query: () => ({
findMany: vi.fn(async ({where, orderBy, limit}) => {
expect(where).toEqual({
publishedAt: {$notNull: true},
bokanteStatusId: {$null: true}
});
expect(orderBy).toEqual({publishedAt: 'asc'});
expect(limit).toBe(1);
return paroles.slice(0, limit);
}),
updateMany
})
},
log: {error: vi.fn(), info: vi.fn()}
};
}
describe('backfillBokanteMirror', () => {
const originalCreateStatus = bokanteMastodon.createStatus;
afterEach(() => {
bokanteMastodon.createStatus = originalCreateStatus;
});
it('publie le miroir pour la parole publiée la plus ancienne sans bokanteStatusId', async () => {
bokanteMastodon.createStatus = vi.fn(async () => ({id: '112233'}));
const parole = {documentId: 'doc-1', titre: 'Vieux titre', slug: 'vieux-titre'};
const strapi = buildStrapi({paroles: [parole]});
const result = await backfillBokanteMirror({strapi});
expect(bokanteMastodon.createStatus).toHaveBeenCalledTimes(1);
expect(bokanteMastodon.createStatus.mock.calls[0][0]).toContain('Vieux titre');
expect(bokanteMastodon.createStatus.mock.calls[0][0]).not.toContain('nouvelle parole');
expect(strapi.db.query().updateMany).toHaveBeenCalledWith({
where: {documentId: 'doc-1'},
data: {bokanteStatusId: '112233'}
});
expect(result).toEqual({backfilled: true, slug: 'vieux-titre'});
});
it('ne fait rien si le catalogue est déjà rattrapé', async () => {
bokanteMastodon.createStatus = vi.fn();
const strapi = buildStrapi({paroles: []});
const result = await backfillBokanteMirror({strapi});
expect(bokanteMastodon.createStatus).not.toHaveBeenCalled();
expect(result).toEqual({backfilled: false});
});
it('n\'interrompt rien si bokante échoue, et ne marque pas la parole comme traitée', async () => {
bokanteMastodon.createStatus = vi.fn(async () => {
throw new Error('boom');
});
const parole = {documentId: 'doc-1', titre: 'Titre', slug: 'titre'};
const strapi = buildStrapi({paroles: [parole]});
const result = await backfillBokanteMirror({strapi});
expect(strapi.log.error).toHaveBeenCalledWith(expect.stringContaining('titre'));
expect(strapi.db.query().updateMany).not.toHaveBeenCalled();
expect(result).toEqual({backfilled: false});
});
});
+36
View File
@@ -0,0 +1,36 @@
'use strict';
const bokanteMastodon = require('./bokante-mastodon');
async function backfillBokanteMirror({strapi}) {
const [parole] = await strapi.db.query('api::parole.parole').findMany({
where: {
publishedAt: {$notNull: true},
bokanteStatusId: {$null: true}
},
orderBy: {publishedAt: 'asc'},
limit: 1
});
if (!parole) {
return {backfilled: false};
}
try {
const status = await bokanteMastodon.createStatus(
`"${parole.titre}" — à (re)découvrir sur pawol.nu\n${process.env.WEBSITE_URL}/paroles/${parole.slug}`
);
await strapi.db.query('api::parole.parole').updateMany({
where: {documentId: parole.documentId},
data: {bokanteStatusId: status.id}
});
return {backfilled: true, slug: parole.slug};
} catch (err) {
strapi.log.error(`Backfill bokante (${parole.slug}) : ${err.message}`);
return {backfilled: false};
}
}
module.exports = {backfillBokanteMirror};