From 69968e52888a18fea965c5343b8653acea3f0ecd Mon Sep 17 00:00:00 2001 From: Hongbo Wu Date: Mon, 24 Apr 2023 12:54:23 +0800 Subject: [PATCH] Save url if the email subject is a parsable url --- packages/api/src/routers/svc/newsletters.ts | 45 +++++++++++++------ .../api/src/services/save_newsletter_email.ts | 4 -- packages/api/src/services/save_url.ts | 44 ++++++++++++++---- packages/api/src/utils/helpers.ts | 9 ++++ 4 files changed, 76 insertions(+), 26 deletions(-) diff --git a/packages/api/src/routers/svc/newsletters.ts b/packages/api/src/routers/svc/newsletters.ts index d8e81f639..cc67a935a 100644 --- a/packages/api/src/routers/svc/newsletters.ts +++ b/packages/api/src/routers/svc/newsletters.ts @@ -1,14 +1,19 @@ import express from 'express' -import { readPushSubscription } from '../../datalayer/pubsub' +import { + createPubSubClient, + readPushSubscription, +} from '../../datalayer/pubsub' import { getNewsletterEmail, updateConfirmationCode, } from '../../services/newsletters' +import { updateReceivedEmail } from '../../services/received_emails' import { NewsletterMessage, saveNewsletterEmail, } from '../../services/save_newsletter_email' -import { updateReceivedEmail } from '../../services/received_emails' +import { saveUrlFromEmail } from '../../services/save_url' +import { isUrl } from '../../utils/helpers' interface SetConfirmationCodeMessage { emailAddress: string @@ -102,27 +107,41 @@ export function newsletterServiceRouter() { const newsletterEmail = await getNewsletterEmail(data.email) if (!newsletterEmail) { console.log('newsletter email not found', data.email) - return false + return res.status(200).send('Not Found') } - const result = await saveNewsletterEmail(data, newsletterEmail) - if (!result) { - console.log( - 'Error creating newsletter link from data', - data.email, + const saveCtx = { + pubsub: createPubSubClient(), + uid: newsletterEmail.user.id, + } + if (isUrl(data.title)) { + // save url if the title is a parsable url + const result = await saveUrlFromEmail( + saveCtx, data.title, - data.author + data.receivedEmailId ) + if (!result) { + return res.status(500).send('Error saving url from email') + } + } else { + // save newsletter instead + const result = await saveNewsletterEmail(data, newsletterEmail, saveCtx) + if (!result) { + console.log( + 'Error creating newsletter link from data', + data.email, + data.title, + data.author + ) - res.status(500).send('Error creating newsletter link') - return + return res.status(500).send('Error creating newsletter link') + } } // update received email type await updateReceivedEmail(data.receivedEmailId, 'article') - // We always send 200 if it was a valid message - // because we don't want the res.status(200).send('newsletter created') } catch (e) { console.log(e) diff --git a/packages/api/src/services/save_newsletter_email.ts b/packages/api/src/services/save_newsletter_email.ts index fdba98824..fd558ae14 100644 --- a/packages/api/src/services/save_newsletter_email.ts +++ b/packages/api/src/services/save_newsletter_email.ts @@ -10,7 +10,6 @@ import { analytics } from '../utils/analytics' import { isBase64Image } from '../utils/helpers' import { fetchFavicon } from '../utils/parser' import { addLabelToPage } from './labels' -import { updateReceivedEmail } from './received_emails' import { SaveContext, saveEmail, SaveEmailInput } from './save_email' import { saveSubscription } from './subscriptions' @@ -63,9 +62,6 @@ export const saveNewsletterEmail = async ( return false } - // update received email type - await updateReceivedEmail(data.receivedEmailId, 'article') - if (!page.siteIcon || isBase64Image(page.siteIcon)) { // fetch favicon if not already set or is a base64 image const favicon = await fetchFavicon(page.url) diff --git a/packages/api/src/services/save_url.ts b/packages/api/src/services/save_url.ts index 7b5695285..93e981d8c 100644 --- a/packages/api/src/services/save_url.ts +++ b/packages/api/src/services/save_url.ts @@ -1,20 +1,20 @@ import { PubsubClient } from '../datalayer/pubsub' -import { UserData } from '../datalayer/user/model' +import { ArticleSavingRequestStatus } from '../elastic/types' +import { User } from '../entity/user' +import { getRepository } from '../entity/utils' import { homePageURL } from '../env' import { SaveErrorCode, SaveResult, SaveUrlInput } from '../generated/graphql' -import { DataModels } from '../resolvers/types' import { createPageSaveRequest } from './create_page_save_request' -import { ArticleSavingRequestStatus } from '../elastic/types' import { createLabels } from './labels' -type SaveContext = { +interface SaveContext { pubsub: PubsubClient - models: DataModels + uid: string } export const saveUrl = async ( ctx: SaveContext, - saver: UserData, + user: User, input: SaveUrlInput ): Promise => { try { @@ -23,28 +23,54 @@ export const saveUrl = async ( input.state === ArticleSavingRequestStatus.Archived ? new Date() : null // add labels to page const labels = input.labels - ? await createLabels({ ...ctx, uid: saver.id }, input.labels) + ? await createLabels({ ...ctx, uid: ctx.uid }, input.labels) : undefined const pageSaveRequest = await createPageSaveRequest({ - userId: saver.id, + userId: ctx.uid, url: input.url, pubsub: ctx.pubsub, articleSavingRequestId: input.clientRequestId, archivedAt, labels, + user, }) return { clientRequestId: pageSaveRequest.id, - url: `${homePageURL()}/${saver.profile.username}/links/${ + url: `${homePageURL()}/${user.profile.username}/links/${ pageSaveRequest.id }`, } } catch (error) { console.log('error enqueuing request', error) return { + __typename: 'SaveError', errorCodes: [SaveErrorCode.Unknown], } } } + +export const saveUrlFromEmail = async ( + ctx: SaveContext, + url: string, + clientRequestId: string +): Promise => { + const user = await getRepository(User).findOneBy({ + id: ctx.uid, + }) + if (!user) { + return false + } + + const result = await saveUrl(ctx, user, { + url, + clientRequestId, + source: 'email', + }) + if (result.__typename === 'SaveError') { + return false + } + + return true +} diff --git a/packages/api/src/utils/helpers.ts b/packages/api/src/utils/helpers.ts index ecf51afc0..0f0861c99 100644 --- a/packages/api/src/utils/helpers.ts +++ b/packages/api/src/utils/helpers.ts @@ -289,3 +289,12 @@ export const generateRandomColor = (): string => { export const unescapeHtml = (html: string): string => { return _.unescape(html) } + +export const isUrl = (str: string): boolean => { + try { + new URL(str) + return true + } catch { + return false + } +}