mirror of
https://github.com/rgrgogu/new_starr.git
synced 2026-09-27 00:12:54 +08:00
60 lines
2.5 KiB
JavaScript
60 lines
2.5 KiB
JavaScript
'use strict';
|
|
|
|
// Reshapes completion_requirement_progress.block_progress from
|
|
// { [blockId]: percentNumber } to { [blockId]: { percent, updatedAt } } so
|
|
// recordWatchProgress can validate a reported percent against real elapsed
|
|
// wall-clock time since that block's last sample (anti-skip hardening —
|
|
// closes the "one API call reports 100%" gaming hole). Applies uniformly to
|
|
// watch_percent rows too, which start using block_progress as of this change
|
|
// (previously only watch_video/listen_audio populated it).
|
|
//
|
|
// Data-only migration — the column type itself (JSONB) doesn't change, so
|
|
// this is a plain JS loop + parameterized UPDATE rather than raw jsonb SQL,
|
|
// consistent with this table's CockroachDB-compatibility precedent (see
|
|
// 20260715000002, which avoids native ALTER TYPE/enum SQL for the same reason).
|
|
|
|
module.exports = {
|
|
async up(queryInterface) {
|
|
const rows = await queryInterface.sequelize.query(
|
|
`SELECT progress_id, block_progress, "updatedAt" FROM completion_requirement_progress WHERE block_progress IS NOT NULL`,
|
|
{ type: queryInterface.sequelize.QueryTypes.SELECT }
|
|
);
|
|
|
|
for (const row of rows) {
|
|
const bp = row.block_progress ?? {};
|
|
const alreadyShaped = Object.values(bp).every((v) => v && typeof v === 'object');
|
|
if (alreadyShaped) continue;
|
|
|
|
const reshaped = Object.fromEntries(
|
|
Object.entries(bp).map(([blockId, percent]) => [
|
|
blockId, { percent: Number(percent) || 0, updatedAt: row.updatedAt ?? new Date().toISOString() },
|
|
])
|
|
);
|
|
|
|
await queryInterface.sequelize.query(
|
|
`UPDATE completion_requirement_progress SET block_progress = :bp WHERE progress_id = :id`,
|
|
{ replacements: { bp: JSON.stringify(reshaped), id: row.progress_id } }
|
|
);
|
|
}
|
|
},
|
|
|
|
async down(queryInterface) {
|
|
const rows = await queryInterface.sequelize.query(
|
|
`SELECT progress_id, block_progress FROM completion_requirement_progress WHERE block_progress IS NOT NULL`,
|
|
{ type: queryInterface.sequelize.QueryTypes.SELECT }
|
|
);
|
|
|
|
for (const row of rows) {
|
|
const bp = row.block_progress ?? {};
|
|
const flattened = Object.fromEntries(
|
|
Object.entries(bp).map(([blockId, v]) => [blockId, v?.percent ?? v])
|
|
);
|
|
|
|
await queryInterface.sequelize.query(
|
|
`UPDATE completion_requirement_progress SET block_progress = :bp WHERE progress_id = :id`,
|
|
{ replacements: { bp: JSON.stringify(flattened), id: row.progress_id } }
|
|
);
|
|
}
|
|
},
|
|
};
|