Skip to content

Commentaires

Endpoints réservés admin (token statique) pour mesurer, inspecter et retirer les commentaires média (media_comment). JSON plat (pas JSON:API). Toutes les mutations sont journalisées par AdminAuditMiddleware (cf. Journal d’audit).

Différences clés avec la surface publique /api/media/comments/* :

  • Aucune rédaction : le body est renvoyé brut même pour un commentaire soft-deleted (le public le masque en null). Un modérateur doit lire ce qui a réellement été écrit.
  • Ids en hex 32 (pas l’UUID à tirets du public), comme le reste de /admin/*.
  • Le DELETE ignore la COMMENT_DELETE_POLICY (author/owner) : un modérateur peut retirer n’importe quel commentaire.

Objet commentaire (plat)

ChampTypeSens
idhex 32id du commentaire
mediaIdhex 32média porteur
userIdhex 32auteur
parentIdhex 32 | nullparent direct (null = top-level)
rootIdhex 32ancêtre top-level (= id si top-level)
depthint0 = top-level, +1 par niveau
isTopLevelboolparentId === null
bodystringtexte brut, jamais masqué
replyCountintenfants directs non supprimés
createdAtISO-8601
editedAtISO-8601 | null
deletedAtISO-8601 | nulltombstone soft-delete
isDeletedbooldeletedAt !== null

Tableau de bord d’engagement des commentaires. Tout vient de la table hxa.media_comment (une seule base) en quelques agrégats GROUP BY / SUM conditionnels — endpoint basse fréquence, pas un hot path. JSON plat.

Query

ParamDéfautSens
days30fenêtre de la courbe quotidienne, borné 1..366

Réponse (200)

  • totals — compteurs globaux. active + deleted = total ; topLevel + replies = active (les soft-deleted sont exclus du découpage de forme pour que le ratio reflète la conversation vivante) ; edited = lignes vivantes amendées au moins une fois.
  • perDay — créations par jour, zéro-rempli (chaque jour de la fenêtre présent, count: 0 les jours creux) pour tracer une courbe continue. Compté par created_at, soft-delete ultérieur inclus (la création est le signal d’engagement).
  • topMedia — 10 médias les plus commentés (commentaires vivants only), name via LEFT JOIN (null si le média a été purgé).
  • topCommenters — 10 comptes les plus actifs (commentaires vivants only), username/nickname via LEFT JOIN (null si le compte a été purgé).
{
"totals": {
"total": 12840,
"active": 12190,
"deleted": 650,
"topLevel": 7320,
"replies": 4870,
"edited": 540
},
"perDay": {
"days": 30,
"from": "2026-05-30",
"to": "2026-06-28",
"total": 1840,
"series": [
{ "date": "2026-05-30", "count": 61 },
{ "date": "2026-05-31", "count": 0 }
]
},
"topMedia": [
{ "mediaId": "9f8e7d6c5b4a39281706f5e4d3c2b1a0", "name": "Sunset over Bali", "count": 184 }
],
"topCommenters": [
{ "userId": "1122334455667788990011223344556677", "username": "marco", "nickname": "Marco P.", "count": 312 }
]
}
Terminal window
# Fenêtre par défaut (30 jours)
curl -s "$BASE/admin/comments/stats" -H "$AUTH"
# Fenêtre d'un an
curl -s "$BASE/admin/comments/stats?days=366" -H "$AUTH"

Erreurs

StatusBodySens
400{ "error": "Invalid days." }days non numérique
403{ "error": "..." }auth KO

Fiche brute d’un commentaire unique. Expose toutes les colonnes, dont le body d’un commentaire soft-deleted et les ids de threading.

Réponse (200) : l’objet commentaire plat décrit ci-dessus.

Terminal window
curl -s "$BASE/admin/comments/0a1b2c3d4e5f60718293a4b5c6d7e8f9" -H "$AUTH"

Erreurs

StatusBodySens
404{ "error": "Comment not found." }row absente ou hex malformé
403{ "error": "..." }auth KO

Soft-delete de modération : pose deleted_at et décrémente les compteurs (reply_count du parent si c’est une réponse, sinon media_stats.comments_count). La ligne est conservée pour ne pas orpheliner les réponses enfants. Ignore la COMMENT_DELETE_POLICY.

Réponse (200) : l’objet commentaire plat post-état (isDeleted: true, deletedAt renseigné, body toujours présent).

Terminal window
curl -s -X DELETE "$BASE/admin/comments/0a1b2c3d4e5f60718293a4b5c6d7e8f9" -H "$AUTH"

Erreurs

StatusBodySens
404{ "error": "Comment not found." }row absente ou hex malformé
410{ "error": "Comment already deleted." }déjà soft-deleted (idempotence stricte)
403{ "error": "..." }auth KO

Notes

  • Aucune notification n’est émise (ni à l’auteur, ni au propriétaire du média) : la modération reste invisible côté produit, comme pour les signalements.
  • Pas de hard-delete : la suppression définitive d’un thread se fait via le hard-delete du média (DELETE /admin/media/{hex}, cascade FK) ou un script de purge dédié.
  • Réversible via POST /admin/comments/{hex}/restore (ci-dessous).

Annule un soft-delete : efface le tombstone deleted_at et ré-incrémente les compteurs que la suppression avait décrémentés (reply_count du parent pour une réponse, sinon media_stats.comments_count).

Réponse (200) : l’objet commentaire plat post-état (isDeleted: false, deletedAt: null).

Terminal window
curl -s -X POST "$BASE/admin/comments/0a1b2c3d4e5f60718293a4b5c6d7e8f9/restore" -H "$AUTH"

Erreurs

StatusBodySens
404{ "error": "Comment not found." }row absente ou hex malformé
409{ "error": "Comment is not deleted." }commentaire déjà actif (rien à restaurer)
403{ "error": "..." }auth KO

Note : un commentaire dont le parent est encore supprimé peut être restauré — reply_count est un cache, la cohérence d’affichage reste gérée côté rendu du thread.


Censure éditoriale : écrase définitivement le body par le message COMMENT_CENSOR_MESSAGE (défaut [Commentaire modéré]). Contrairement au soft-delete, le commentaire reste visible — la structure du thread est préservée et un lecteur voit la notice de modération à la place du texte original.

Le texte original n’est pas archivé : l’opération est irréversible (il n’existe pas de pendant « uncensor » ; pour re-masquer sans effacer, utiliser DELETE /admin/comments/{hex}). Les compteurs (reply_count, media_stats.comments_count) restent inchangés — le commentaire compte toujours. edited_at n’est pas touché (ce n’est pas une édition d’auteur).

Réponse (200) : l’objet commentaire plat post-étatbody vaut le message de censure, isDeleted inchangé.

Terminal window
curl -s -X POST "$BASE/admin/comments/0a1b2c3d4e5f60718293a4b5c6d7e8f9/censor" -H "$AUTH"

Erreurs

StatusBodySens
404{ "error": "Comment not found." }row absente ou hex malformé
403{ "error": "..." }auth KO

Notes

  • Idempotent : re-censurer réécrit simplement le même message (200).
  • Aucune notification émise (comme le soft-delete de modération).
  • Le message de remplacement est stocké tel quel dans body (chaîne figée, pas de résolution i18n au rendu) : il s’affiche à l’identique pour toutes les locales. Ajuster COMMENT_CENSOR_MESSAGE en amont si besoin.