From a6795b380a272e8f6a1c502c097f0a7aa3216f8d Mon Sep 17 00:00:00 2001 From: Hongbo Wu Date: Wed, 28 Sep 2022 19:02:29 +0800 Subject: [PATCH] Fetch favicon from url --- packages/api/src/elastic/types.ts | 2 ++ packages/api/src/generated/graphql.ts | 2 ++ packages/api/src/generated/schema.graphql | 1 + packages/api/src/resolvers/article/index.ts | 1 + packages/api/src/resolvers/subscriptions/index.ts | 2 +- packages/api/src/schema.ts | 1 + .../api/src/services/save_newsletter_email.ts | 12 +++++++++++- packages/api/src/utils/parser.ts | 15 +++++++++++++++ 8 files changed, 34 insertions(+), 2 deletions(-) diff --git a/packages/api/src/elastic/types.ts b/packages/api/src/elastic/types.ts index 33d00b038..065770aa6 100644 --- a/packages/api/src/elastic/types.ts +++ b/packages/api/src/elastic/types.ts @@ -247,6 +247,8 @@ export interface SearchItem { labels?: Label[] highlights?: Highlight[] wordsCount?: number + siteName?: string + siteIcon?: string } const keys = ['_id', 'url', 'slug', 'userId', 'uploadFileId', 'state'] as const diff --git a/packages/api/src/generated/graphql.ts b/packages/api/src/generated/graphql.ts index 0ddc4a9bc..24f683035 100644 --- a/packages/api/src/generated/graphql.ts +++ b/packages/api/src/generated/graphql.ts @@ -1644,6 +1644,7 @@ export type SearchItem = { readingProgressPercent: Scalars['Float']; savedAt: Scalars['Date']; shortId?: Maybe; + siteIcon?: Maybe; siteName?: Maybe; slug: Scalars['String']; state?: Maybe; @@ -4160,6 +4161,7 @@ export type SearchItemResolvers; savedAt?: Resolver; shortId?: Resolver, ParentType, ContextType>; + siteIcon?: Resolver, ParentType, ContextType>; siteName?: Resolver, ParentType, ContextType>; slug?: Resolver; state?: Resolver, ParentType, ContextType>; diff --git a/packages/api/src/generated/schema.graphql b/packages/api/src/generated/schema.graphql index e84f2a647..a15f5c497 100644 --- a/packages/api/src/generated/schema.graphql +++ b/packages/api/src/generated/schema.graphql @@ -1170,6 +1170,7 @@ type SearchItem { readingProgressPercent: Float! savedAt: Date! shortId: String + siteIcon: String siteName: String slug: String! state: ArticleSavingRequestStatus diff --git a/packages/api/src/resolvers/article/index.ts b/packages/api/src/resolvers/article/index.ts index e9b214102..40b77af12 100644 --- a/packages/api/src/resolvers/article/index.ts +++ b/packages/api/src/resolvers/article/index.ts @@ -899,6 +899,7 @@ export const searchResolver = authorized< publishedAt: validatedDate(r.publishedAt), ownedByViewer: r.userId === claims.uid, pageType: r.pageType || PageType.Highlights, + siteIcon: r.siteIcon && createImageProxyUrl(r.siteIcon, 32, 32), } as SearchItem, cursor: endCursor, } diff --git a/packages/api/src/resolvers/subscriptions/index.ts b/packages/api/src/resolvers/subscriptions/index.ts index a9c6f123e..eb416b868 100644 --- a/packages/api/src/resolvers/subscriptions/index.ts +++ b/packages/api/src/resolvers/subscriptions/index.ts @@ -60,7 +60,7 @@ export const subscriptionsResolver = authorized< return { subscriptions: subscriptions.map((s) => ({ ...s, - icon: s.icon && createImageProxyUrl(s.icon, 260, 260), + icon: s.icon && createImageProxyUrl(s.icon, 32, 32), })), } } catch (error) { diff --git a/packages/api/src/schema.ts b/packages/api/src/schema.ts index 752b69b76..c2e6f3805 100755 --- a/packages/api/src/schema.ts +++ b/packages/api/src/schema.ts @@ -1495,6 +1495,7 @@ const schema = gql` readAt: Date savedAt: Date! highlights: [Highlight!] + siteIcon: String } type SearchItemEdge { diff --git a/packages/api/src/services/save_newsletter_email.ts b/packages/api/src/services/save_newsletter_email.ts index 4db8373ad..84daf9a40 100644 --- a/packages/api/src/services/save_newsletter_email.ts +++ b/packages/api/src/services/save_newsletter_email.ts @@ -12,6 +12,8 @@ import { Page } from '../elastic/types' import { addLabelToPage } from './labels' import { saveSubscription } from './subscriptions' import { NewsletterEmail } from '../entity/newsletter_email' +import { fetchFavicon } from '../utils/parser' +import { updatePage } from '../elastic/pages' interface NewsletterMessage { email: string @@ -22,7 +24,6 @@ interface NewsletterMessage { unsubMailTo?: string unsubHttpUrl?: string newsletterEmail?: NewsletterEmail - icon?: string } // Returns true if the link was created successfully. Can still fail to @@ -68,6 +69,15 @@ export const saveNewsletterEmail = async ( return false } + if (!page.siteIcon) { + // fetch favicon if not already set + const favicon = await fetchFavicon(page.url) + if (favicon) { + page.siteIcon = favicon + await updatePage(page.id, { siteIcon: favicon }, saveCtx) + } + } + // creates or updates subscription const subscription = await saveSubscription({ userId: newsletterEmail.user.id, diff --git a/packages/api/src/utils/parser.ts b/packages/api/src/utils/parser.ts index 01e97d0bd..05f6df6b5 100644 --- a/packages/api/src/utils/parser.ts +++ b/packages/api/src/utils/parser.ts @@ -621,3 +621,18 @@ export const parseEmailAddress = (from: string): addressparser.EmailAddress => { } return { name: '', address: from } } + +export const fetchFavicon = async ( + url: string +): Promise => { + try { + // get the correct url if it's a redirect + const response = await axios.head(url) + const realUrl = response.request.res.responseUrl + const domain = new URL(realUrl).hostname + return `https://api.faviconkit.com/${domain}/32` + } catch (e) { + console.log('Error fetching favicon', e) + return undefined + } +}