From acfbc80d1a01d02d32b05011d3fdec7d1f4e5349 Mon Sep 17 00:00:00 2001 From: echo Date: Sun, 1 Feb 2026 13:57:16 +0100 Subject: [PATCH] unpublish fix --- backend/src/modules/strapi.controller.ts | 6 +- backend/src/modules/strapi.service.ts | 120 ++++++++++++++++++----- 2 files changed, 99 insertions(+), 27 deletions(-) diff --git a/backend/src/modules/strapi.controller.ts b/backend/src/modules/strapi.controller.ts index a5b0627..cf4fede 100644 --- a/backend/src/modules/strapi.controller.ts +++ b/backend/src/modules/strapi.controller.ts @@ -2,7 +2,7 @@ import { Controller, Post, Body, Logger } from '@nestjs/common'; import { StrapiService } from './strapi.service'; interface WebhookBody { - event: 'entry.create' | 'entry.update' | 'entry.delete' | 'entry.publish'; + event: 'entry.create' | 'entry.update' | 'entry.delete' | 'entry.publish' | 'entry.unpublish'; model: string; entry: { documentId: string; @@ -91,6 +91,7 @@ export class StrapiController { 'entry.update', 'entry.delete', 'entry.publish', + 'entry.unpublish', ]; if (!validEvents.includes(event)) { this.logger.warn(`Invalid event type: ${event}`); @@ -102,7 +103,8 @@ export class StrapiController { | 'entry.create' | 'entry.update' | 'entry.delete' - | 'entry.publish', + | 'entry.publish' + | 'entry.unpublish', { documentId, model }, ); return { message: 'Webhook processed successfully' }; diff --git a/backend/src/modules/strapi.service.ts b/backend/src/modules/strapi.service.ts index 7b1bb14..721ba6d 100644 --- a/backend/src/modules/strapi.service.ts +++ b/backend/src/modules/strapi.service.ts @@ -115,9 +115,12 @@ export class StrapiService { } } - async syncSingleArticle(strapiId: string): Promise { + async syncSingleArticle( + strapiId: string, + event?: 'entry.create' | 'entry.update' | 'entry.delete' | 'entry.publish' | 'entry.unpublish', + ): Promise { try { - this.logger.log(`Syncing single article from Strapi: ${strapiId}`); + this.logger.log(`Syncing single article from Strapi: ${strapiId}, event: ${event}`); const response = await lastValueFrom( this.httpService.get>( @@ -129,14 +132,26 @@ export class StrapiService { ); const strapiArticle = response.data.data; + + // Determine status based on publishedAt and event type + let status: ArticleStatus; + if (event === 'entry.unpublish') { + // If it's an unpublish event, always mark as draft + status = ArticleStatus.DRAFT; + } else if (strapiArticle.publishedAt) { + // If publishedAt exists, it's published + status = ArticleStatus.PUBLISHED; + } else { + // Otherwise it's a draft + status = ArticleStatus.DRAFT; + } + const articleData: Partial = { title: strapiArticle.title, excerpt: strapiArticle.description, content: strapiArticle.content, slug: strapiArticle.slug, - status: strapiArticle.publishedAt - ? ArticleStatus.PUBLISHED - : ArticleStatus.DRAFT, + status, tags: [], }; @@ -144,13 +159,34 @@ export class StrapiService { strapiArticle.documentId, articleData, ); - this.logger.log(`Successfully synced article: ${strapiArticle.title}`); - } catch (error) { - this.logger.error( - `Failed to sync article ${strapiId} from Strapi`, - error, - ); - throw error; + this.logger.log(`Successfully synced article: ${strapiArticle.title} with status: ${status}`); + } catch (error: any) { + // If we get a 404 and it's an unpublish event, we can still mark it as draft + if (event === 'entry.unpublish' && error.response?.status === 404) { + this.logger.log(`Article ${strapiId} not found in Strapi, marking as draft based on unpublish event`); + + // Try to update the article status to draft directly + try { + const articleData: Partial = { + status: ArticleStatus.DRAFT, + }; + + await this.articlesService.syncFromStrapi(strapiId, articleData); + this.logger.log(`Marked article ${strapiId} as draft based on unpublish event`); + } catch (syncError) { + this.logger.error( + `Failed to mark article ${strapiId} as draft:`, + syncError, + ); + throw syncError; + } + } else { + this.logger.error( + `Failed to sync article ${strapiId} from Strapi`, + error, + ); + throw error; + } } } @@ -194,9 +230,12 @@ export class StrapiService { } } - async syncSingleLiveBlog(strapiId: string): Promise { + async syncSingleLiveBlog( + strapiId: string, + event?: 'entry.create' | 'entry.update' | 'entry.delete' | 'entry.publish' | 'entry.unpublish', + ): Promise { try { - this.logger.log(`Syncing single live blog from Strapi: ${strapiId}`); + this.logger.log(`Syncing single live blog from Strapi: ${strapiId}, event: ${event}`); const response = await lastValueFrom( this.httpService.get>( @@ -208,24 +247,55 @@ export class StrapiService { ); const strapiLiveBlog = response.data.data; + + // For live blogs, we use the status from Strapi directly + // but we might want to handle unpublish events differently + let status = this.mapStrapiStatusToLiveBlogStatus(strapiLiveBlog.status); + + // If it's an unpublish event, set to draft + if (event === 'entry.unpublish') { + status = LiveBlogStatus.DRAFT; + } + const liveBlogData: Partial = { title: strapiLiveBlog.title, description: strapiLiveBlog.description, slug: strapiLiveBlog.slug, - status: this.mapStrapiStatusToLiveBlogStatus(strapiLiveBlog.status), + status, }; await this.liveBlogService.syncFromStrapi( strapiLiveBlog.documentId, liveBlogData, ); - this.logger.log(`Successfully synced live blog: ${strapiLiveBlog.title}`); - } catch (error) { - this.logger.error( - `Failed to sync live blog ${strapiId} from Strapi`, - error, - ); - throw error; + this.logger.log(`Successfully synced live blog: ${strapiLiveBlog.title} with status: ${status}`); + } catch (error: any) { + // If we get a 404 and it's an unpublish event, we can still mark it as draft + if (event === 'entry.unpublish' && error.response?.status === 404) { + this.logger.log(`Live blog ${strapiId} not found in Strapi, marking as draft based on unpublish event`); + + // Try to update the live blog status to draft directly + try { + const liveBlogData: Partial = { + status: LiveBlogStatus.DRAFT, + }; + + await this.liveBlogService.syncFromStrapi(strapiId, liveBlogData); + this.logger.log(`Marked live blog ${strapiId} as draft based on unpublish event`); + } catch (syncError) { + this.logger.error( + `Failed to mark live blog ${strapiId} as draft:`, + syncError, + ); + throw syncError; + } + } else { + this.logger.error( + `Failed to sync live blog ${strapiId} from Strapi`, + error, + ); + throw error; + } } } @@ -245,7 +315,7 @@ export class StrapiService { } async handleWebhook( - event: 'entry.create' | 'entry.update' | 'entry.delete' | 'entry.publish', + event: 'entry.create' | 'entry.update' | 'entry.delete' | 'entry.publish' | 'entry.unpublish', data: { documentId: string; model?: string }, ): Promise { this.logger.log( @@ -259,9 +329,9 @@ export class StrapiService { // Route to appropriate sync method based on model if (data.model === 'article') { - await this.syncSingleArticle(data.documentId); + await this.syncSingleArticle(data.documentId, event); } else if (data.model === 'live-blog') { - await this.syncSingleLiveBlog(data.documentId); + await this.syncSingleLiveBlog(data.documentId, event); } else { this.logger.warn(`Unknown model type in webhook: ${data.model}`); }