diff --git a/.changeset/seven-deer-marry.md b/.changeset/seven-deer-marry.md new file mode 100644 index 0000000000..a845151cc8 --- /dev/null +++ b/.changeset/seven-deer-marry.md @@ -0,0 +1,2 @@ +--- +--- diff --git a/server/src/addie/services/feed-fetcher.ts b/server/src/addie/services/feed-fetcher.ts index a995687248..709b02a6ed 100644 --- a/server/src/addie/services/feed-fetcher.ts +++ b/server/src/addie/services/feed-fetcher.ts @@ -68,7 +68,7 @@ function validateRssContent(content: string, contentType: string): { valid: bool } interface FeedItem { - guid?: string; + guid?: string | { _: string }; link?: string; title?: string; pubDate?: string; @@ -144,7 +144,11 @@ async function fetchFeed(feed: IndustryFeed): Promise { } // Generate a stable GUID - const guid = item.guid || item.link; + // Handle RSS guids that may be objects with _ property (from XML attributes) + const rawGuid = item.guid; + const guid = typeof rawGuid === 'object' && rawGuid !== null && '_' in rawGuid + ? rawGuid._ + : (rawGuid || item.link); // Parse publication date let publishedAt: Date | undefined; diff --git a/server/src/db/industry-feeds-db.ts b/server/src/db/industry-feeds-db.ts index 0ee2c4d99c..c22f15fc05 100644 --- a/server/src/db/industry-feeds-db.ts +++ b/server/src/db/industry-feeds-db.ts @@ -243,8 +243,14 @@ function generateSlug(title: string, guid: string): string { .replace(/^-|-$/g, '') .substring(0, 80); + // Ensure guid is a string (defensive against RSS parser quirks) + if (typeof guid !== 'string') { + logger.warn({ guid, title }, 'generateSlug received non-string guid'); + } + const guidStr = String(guid || ''); + // Add a hash of the guid to ensure uniqueness - const hash = Math.abs(guid.split('').reduce((a, b) => { + const hash = Math.abs(guidStr.split('').reduce((a, b) => { a = ((a << 5) - a) + b.charCodeAt(0); return a & a; }, 0)).toString(36).substring(0, 6); diff --git a/server/src/routes/admin/organizations.ts b/server/src/routes/admin/organizations.ts index 8675afeb50..1200d98c8b 100644 --- a/server/src/routes/admin/organizations.ts +++ b/server/src/routes/admin/organizations.ts @@ -1162,8 +1162,8 @@ export function setupOrganizationRoutes( // Add membership to the new org await pool.query( `INSERT INTO organization_memberships - (workos_user_id, workos_organization_id, email, first_name, last_name, role) - VALUES ($1, $2, $3, $4, $5, 'member') + (workos_user_id, workos_organization_id, email, first_name, last_name) + VALUES ($1, $2, $3, $4, $5) ON CONFLICT (workos_user_id, workos_organization_id) DO UPDATE SET email = EXCLUDED.email, first_name = EXCLUDED.first_name, last_name = EXCLUDED.last_name`, [userId, orgId, user.email, user.first_name, user.last_name]