Social feeds
Un social feed regroupe entre SOCIAL_FEED_MEDIA_MIN et SOCIAL_FEED_MEDIA_MAX (par défaut 1 à 15) des médias publiés de l’utilisateur connecté sous un code court (Crockford Base32, 4..10 caractères) qu’on peut partager hors-plateforme (réseaux sociaux, e-mail, SMS…). Le destinataire ouvre l’URL /api/social-feeds/{code} et reçoit la liste complète du carrousel en un seul appel.
Codes : alphabet 0123456789ABCDEFGHJKMNPQRSTVWXYZ (Crockford, sans I/L/O/U → pas d’ambiguïté oral/saisie). Longueur initiale 4 (env SOCIAL_FEED_CODE_LENGTH, ≈ 1.05M codes uniques). Quand les collisions saturent la file de tentatives (SOCIAL_FEED_CODE_MAX_ATTEMPTS, défaut 5), le générateur renvoie 503 socialFeed.codeExhausted — signal d’ops pour passer la longueur à 5, 6, etc., jusqu’à la borne de la colonne (VARCHAR(10)). Les codes courts déjà émis restent valides.
Règles produit :
- Pas de XP, pas de notification, pas de compteur public.
- Les médias d’un feed doivent exister, être publiés ET appartenir à l’auteur. Un média dépublié après la création du feed est silencieusement filtré de la lecture publique (la ligne reste en DB).
- L’ordre des
mediaIdsau POST est l’ordre du carrousel (position1..N en base, contrainte UNIQUE). - Un feed est permanent ; seul son auteur peut le supprimer (
DELETE /api/users/me/social-feeds/{code}). - Lecture publique anonyme OK (la share URL ne nécessite pas d’auth) ; un viewer authentifié récupère en plus son
viewerReactionsur chaque média du carrousel.
POST /api/users/me/social-feeds
Section titled “POST /api/users/me/social-feeds”Crée un feed. Auth requise. Le body accepte la forme JSON:API (data.attributes.mediaIds) ou plate ({ "mediaIds": [...] }).
{ "data": { "attributes": { "mediaIds": [ "11111111-1111-1111-1111-111111111111", "22222222-2222-2222-2222-222222222222", "33333333-3333-3333-3333-333333333333" ] } }}Réponse 201 :
{ "data": { "type": "socialFeeds", "id": "7JBQ", "attributes": { "userId": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa", "mediaCount": 3, "mediaIds": [ "11111111-1111-1111-1111-111111111111", "22222222-2222-2222-2222-222222222222", "33333333-3333-3333-3333-333333333333" ], "createdAt": { "iso": "...", "formatted": { "...": "..." }, "relative": "..." } } }}Erreurs (422 sauf indication) :
| Code | Raison |
|---|---|
socialFeed.actorNotConfirmed | (403) compte non confirmé |
socialFeed.actorBanned | (403) compte banni |
socialFeed.tooFewMedias | moins de SOCIAL_FEED_MEDIA_MIN médias |
socialFeed.tooManyMedias | plus de SOCIAL_FEED_MEDIA_MAX médias |
socialFeed.duplicateMedia | un même mediaId apparaît plusieurs fois |
socialFeed.mediaNotFound | un mediaId n’existe pas ou n’est pas publié |
socialFeed.mediaNotOwned | un mediaId n’appartient pas à l’utilisateur |
socialFeed.codeExhausted | (503) bumpez SOCIAL_FEED_CODE_LENGTH |
GET /api/users/me/social-feeds
Section titled “GET /api/users/me/social-feeds”Liste les feeds de l’utilisateur authentifié, du plus récent au plus ancien. Paramètre ?limit= (1..100, défaut 50). Pas de pagination keyset — la volumétrie attendue par utilisateur est faible. meta.total est exact.
Chaque ressource expose mediaIds (UUIDs ordonnés) — pas les médias complets ; le client utilise les UUIDs pour résoudre les thumbnails via les URLs media existantes. ListMySocialFeedsAction
DELETE /api/users/me/social-feeds/{code}
Section titled “DELETE /api/users/me/social-feeds/{code}”Supprime un feed appartenant à l’utilisateur connecté. 204 en cas de succès. 404 socialFeed.notFound lorsque le code n’existe pas OU appartient à un autre utilisateur (confusion délibérée pour éviter l’énumération des codes par sonde DELETE). DeleteSocialFeedAction
GET /api/social-feeds/{code}
Section titled “GET /api/social-feeds/{code}”Lecture publique : pas d’auth requise (anonymous OK via OptionalAuthenticationMiddleware). Retourne la ressource feed avec :
mediaIds— UUIDs ordonnés du carrousel ;medias— la liste complète des médias hydratés (mêmes attributs queGET /api/media/{id}:url,blurhashUrl,latitude/longitude,authorpublic,likesCount, etc.), dans l’ordre du carrousel. Les médias dépubliés depuis la création sont filtrés ;medias.lengthpeut donc être strictement inférieur àmediaCount.
Un viewer authentifié reçoit en plus viewerReaction sur chaque média.
404 socialFeed.notFound si le code n’a pas la bonne forme (longueur/alphabet) ou n’existe pas — même réponse pour les deux cas. GetSocialFeedAction