diff --git a/packages/api/src/entity/newsletter_email.ts b/packages/api/src/entity/newsletter_email.ts index 707dcf379..312cc6b14 100644 --- a/packages/api/src/entity/newsletter_email.ts +++ b/packages/api/src/entity/newsletter_email.ts @@ -34,4 +34,13 @@ export class NewsletterEmail { @OneToMany(() => Subscription, (subscription) => subscription.newsletterEmail) subscriptions!: Subscription[] + + @Column('text') + folder!: string + + @Column('text') + name?: string | null + + @Column('text') + description?: string | null } diff --git a/packages/api/src/entity/subscription.ts b/packages/api/src/entity/subscription.ts index 10416a551..2b240e8e5 100644 --- a/packages/api/src/entity/subscription.ts +++ b/packages/api/src/entity/subscription.ts @@ -76,4 +76,10 @@ export class Subscription { @Column('boolean') autoAddToLibrary?: boolean | null + + @Column('boolean') + fetchContent!: boolean + + @Column('text') + folder!: string } diff --git a/packages/api/src/generated/graphql.ts b/packages/api/src/generated/graphql.ts index a3d814b9f..aed124467 100644 --- a/packages/api/src/generated/graphql.ts +++ b/packages/api/src/generated/graphql.ts @@ -438,6 +438,12 @@ export enum CreateNewsletterEmailErrorCode { Unauthorized = 'UNAUTHORIZED' } +export type CreateNewsletterEmailInput = { + description?: InputMaybe; + folder?: InputMaybe; + name?: InputMaybe; +}; + export type CreateNewsletterEmailResult = CreateNewsletterEmailError | CreateNewsletterEmailSuccess; export type CreateNewsletterEmailSuccess = { @@ -1415,6 +1421,11 @@ export type MutationCreateLabelArgs = { }; +export type MutationCreateNewsletterEmailArgs = { + input?: InputMaybe; +}; + + export type MutationDeleteAccountArgs = { userID: Scalars['ID']; }; @@ -1677,7 +1688,10 @@ export type NewsletterEmail = { address: Scalars['String']; confirmationCode?: Maybe; createdAt: Scalars['Date']; + description?: Maybe; + folder: Scalars['String']; id: Scalars['ID']; + name?: Maybe; subscriptionCount: Scalars['Int']; }; @@ -2752,6 +2766,8 @@ export enum SubscribeErrorCode { export type SubscribeInput = { autoAddToLibrary?: InputMaybe; + fetchContent?: InputMaybe; + folder?: InputMaybe; isPrivate?: InputMaybe; subscriptionType?: InputMaybe; url: Scalars['String']; @@ -2770,6 +2786,8 @@ export type Subscription = { count: Scalars['Int']; createdAt: Scalars['Date']; description?: Maybe; + fetchContent: Scalars['Boolean']; + folder: Scalars['String']; icon?: Maybe; id: Scalars['ID']; isPrivate?: Maybe; @@ -3116,6 +3134,8 @@ export enum UpdateSubscriptionErrorCode { export type UpdateSubscriptionInput = { autoAddToLibrary?: InputMaybe; description?: InputMaybe; + fetchContent?: InputMaybe; + folder?: InputMaybe; id: Scalars['ID']; isPrivate?: InputMaybe; lastFetchedAt?: InputMaybe; @@ -3526,6 +3546,7 @@ export type ResolversTypes = { CreateLabelSuccess: ResolverTypeWrapper; CreateNewsletterEmailError: ResolverTypeWrapper; CreateNewsletterEmailErrorCode: CreateNewsletterEmailErrorCode; + CreateNewsletterEmailInput: CreateNewsletterEmailInput; CreateNewsletterEmailResult: ResolversTypes['CreateNewsletterEmailError'] | ResolversTypes['CreateNewsletterEmailSuccess']; CreateNewsletterEmailSuccess: ResolverTypeWrapper; CreateReactionError: ResolverTypeWrapper; @@ -4036,6 +4057,7 @@ export type ResolversParentTypes = { CreateLabelResult: ResolversParentTypes['CreateLabelError'] | ResolversParentTypes['CreateLabelSuccess']; CreateLabelSuccess: CreateLabelSuccess; CreateNewsletterEmailError: CreateNewsletterEmailError; + CreateNewsletterEmailInput: CreateNewsletterEmailInput; CreateNewsletterEmailResult: ResolversParentTypes['CreateNewsletterEmailError'] | ResolversParentTypes['CreateNewsletterEmailSuccess']; CreateNewsletterEmailSuccess: CreateNewsletterEmailSuccess; CreateReactionError: CreateReactionError; @@ -5345,7 +5367,7 @@ export type MutationResolvers>; createHighlight?: Resolver>; createLabel?: Resolver>; - createNewsletterEmail?: Resolver; + createNewsletterEmail?: Resolver>; deleteAccount?: Resolver>; deleteFilter?: Resolver>; deleteHighlight?: Resolver>; @@ -5404,7 +5426,10 @@ export type NewsletterEmailResolvers; confirmationCode?: Resolver, ParentType, ContextType>; createdAt?: Resolver; + description?: Resolver, ParentType, ContextType>; + folder?: Resolver; id?: Resolver; + name?: Resolver, ParentType, ContextType>; subscriptionCount?: Resolver; __isTypeOf?: IsTypeOfResolverFn; }; @@ -6036,6 +6061,8 @@ export type SubscriptionResolvers; createdAt?: SubscriptionResolver; description?: SubscriptionResolver, "description", ParentType, ContextType>; + fetchContent?: SubscriptionResolver; + folder?: SubscriptionResolver; icon?: SubscriptionResolver, "icon", ParentType, ContextType>; id?: SubscriptionResolver; isPrivate?: SubscriptionResolver, "isPrivate", ParentType, ContextType>; diff --git a/packages/api/src/generated/schema.graphql b/packages/api/src/generated/schema.graphql index e57928d48..44f35d093 100644 --- a/packages/api/src/generated/schema.graphql +++ b/packages/api/src/generated/schema.graphql @@ -383,6 +383,12 @@ enum CreateNewsletterEmailErrorCode { UNAUTHORIZED } +input CreateNewsletterEmailInput { + description: String + folder: String + name: String +} + union CreateNewsletterEmailResult = CreateNewsletterEmailError | CreateNewsletterEmailSuccess type CreateNewsletterEmailSuccess { @@ -1182,7 +1188,7 @@ type Mutation { createGroup(input: CreateGroupInput!): CreateGroupResult! createHighlight(input: CreateHighlightInput!): CreateHighlightResult! createLabel(input: CreateLabelInput!): CreateLabelResult! - createNewsletterEmail: CreateNewsletterEmailResult! + createNewsletterEmail(input: CreateNewsletterEmailInput): CreateNewsletterEmailResult! deleteAccount(userID: ID!): DeleteAccountResult! deleteFilter(id: ID!): DeleteFilterResult! deleteHighlight(highlightId: ID!): DeleteHighlightResult! @@ -1241,7 +1247,10 @@ type NewsletterEmail { address: String! confirmationCode: String createdAt: Date! + description: String + folder: String! id: ID! + name: String subscriptionCount: Int! } @@ -2169,6 +2178,8 @@ enum SubscribeErrorCode { input SubscribeInput { autoAddToLibrary: Boolean + fetchContent: Boolean + folder: String isPrivate: Boolean subscriptionType: SubscriptionType url: String! @@ -2185,6 +2196,8 @@ type Subscription { count: Int! createdAt: Date! description: String + fetchContent: Boolean! + folder: String! icon: String id: ID! isPrivate: Boolean @@ -2504,6 +2517,8 @@ enum UpdateSubscriptionErrorCode { input UpdateSubscriptionInput { autoAddToLibrary: Boolean description: String + fetchContent: Boolean + folder: String id: ID! isPrivate: Boolean lastFetchedAt: Date diff --git a/packages/api/src/resolvers/article/index.ts b/packages/api/src/resolvers/article/index.ts index cc373cbfc..7d3fea678 100644 --- a/packages/api/src/resolvers/article/index.ts +++ b/packages/api/src/resolvers/article/index.ts @@ -415,7 +415,6 @@ export const getArticleResolver = authorized< deletedAt: IsNull(), }, relations: { - labels: true, highlights: { user: true, labels: true, @@ -912,7 +911,7 @@ export const moveToFolderResolver = authorized< MoveToFolderSuccess, MoveToFolderError, MutationMoveToFolderArgs ->(async (_, { id, folder }, { authTrx, pubsub, uid }) => { +>(async (_, { id, folder }, { authTrx, log, pubsub, uid }) => { analytics.track({ userId: uid, event: 'move_to_folder', @@ -945,24 +944,6 @@ export const moveToFolderResolver = authorized< const savedAt = new Date() - // // if the content is not fetched yet, create a page save request - // if (!item.readableContent) { - // const articleSavingRequest = await createPageSaveRequest({ - // userId: uid, - // url: item.originalUrl, - // articleSavingRequestId: id, - // priority: 'high', - // publishedAt: item.publishedAt || undefined, - // savedAt, - // pubsub, - // }) - - // return { - // __typename: 'MoveToFolderSuccess', - // articleSavingRequest, - // } - // } - await updateLibraryItem( item.id, { @@ -973,8 +954,29 @@ export const moveToFolderResolver = authorized< pubsub ) + // if the content is not fetched yet, create a page save request + if (!item.readableContent) { + try { + await createPageSaveRequest({ + userId: uid, + url: item.originalUrl, + articleSavingRequestId: id, + priority: 'high', + publishedAt: item.publishedAt || undefined, + savedAt, + folder, + pubsub, + }) + } catch (error) { + log.error('moveToFolderResolver error', error) + + return { + errorCodes: [MoveToFolderErrorCode.BadRequest], + } + } + } + return { - __typename: 'MoveToFolderSuccess', success: true, } }) diff --git a/packages/api/src/resolvers/function_resolvers.ts b/packages/api/src/resolvers/function_resolvers.ts index 9663d72bc..398ac284c 100644 --- a/packages/api/src/resolvers/function_resolvers.ts +++ b/packages/api/src/resolvers/function_resolvers.ts @@ -319,6 +319,19 @@ export const functionResolvers = { if (article.wordCount) return article.wordCount return article.content ? wordsCount(article.content) : undefined }, + async labels( + article: { id: string; labels?: Label[]; labelNames?: string[] | null }, + _: unknown, + ctx: WithDataSourcesContext + ) { + if (article.labels) return article.labels + + if (article.labelNames && article.labelNames.length > 0) { + return findLabelsByLibraryItemId(article.id, ctx.uid) + } + + return [] + }, }, Highlight: { // async reactions( @@ -518,4 +531,5 @@ export const functionResolvers = { ...resultResolveTypeResolver('UpdateSubscription'), ...resultResolveTypeResolver('UpdateEmail'), ...resultResolveTypeResolver('ScanFeeds'), + ...resultResolveTypeResolver('MoveToFolder'), } diff --git a/packages/api/src/resolvers/newsletters/index.ts b/packages/api/src/resolvers/newsletters/index.ts index 49f13b090..8e1e4ec9a 100644 --- a/packages/api/src/resolvers/newsletters/index.ts +++ b/packages/api/src/resolvers/newsletters/index.ts @@ -7,6 +7,7 @@ import { DeleteNewsletterEmailError, DeleteNewsletterEmailErrorCode, DeleteNewsletterEmailSuccess, + MutationCreateNewsletterEmailArgs, MutationDeleteNewsletterEmailArgs, NewsletterEmailsError, NewsletterEmailsErrorCode, @@ -24,8 +25,9 @@ import { authorized } from '../../utils/helpers' export const createNewsletterEmailResolver = authorized< CreateNewsletterEmailSuccess, - CreateNewsletterEmailError ->(async (_parent, _args, { claims, log }) => { + CreateNewsletterEmailError, + MutationCreateNewsletterEmailArgs +>(async (_parent, { input }, { claims, log }) => { log.info('createNewsletterEmailResolver') analytics.track({ userId: claims.uid, @@ -36,7 +38,13 @@ export const createNewsletterEmailResolver = authorized< }) try { - const newsletterEmail = await createNewsletterEmail(claims.uid) + const newsletterEmail = await createNewsletterEmail( + claims.uid, + undefined, + input?.folder || 'following', + input?.name || undefined, + input?.description || undefined + ) return { newsletterEmail: { @@ -45,7 +53,7 @@ export const createNewsletterEmailResolver = authorized< }, } } catch (e) { - log.info(e) + log.error('createNewsletterEmailResolver', e) return { errorCodes: [CreateNewsletterEmailErrorCode.BadRequest], @@ -67,7 +75,7 @@ export const newsletterEmailsResolver = authorized< })), } } catch (e) { - log.info(e) + log.error('newsletterEmailsResolver', e) return { errorCodes: [NewsletterEmailsErrorCode.BadRequest], diff --git a/packages/api/src/resolvers/subscriptions/index.ts b/packages/api/src/resolvers/subscriptions/index.ts index d6cc7b34d..6489e80c7 100644 --- a/packages/api/src/resolvers/subscriptions/index.ts +++ b/packages/api/src/resolvers/subscriptions/index.ts @@ -206,6 +206,9 @@ export const subscribeResolver = authorized< // re-subscribe const updatedSubscription = await getRepository(Subscription).save({ ...existingSubscription, + fetchContent: input.fetchContent ?? undefined, + folder: input.folder ?? undefined, + isPrivate: input.isPrivate, status: SubscriptionStatus.Active, }) @@ -217,7 +220,8 @@ export const subscribeResolver = authorized< scheduledDates: [new Date()], // fetch immediately fetchedDates: [updatedSubscription.lastFetchedAt || null], checksums: [updatedSubscription.lastFetchedChecksum || null], - addToLibraryFlags: [!!updatedSubscription.autoAddToLibrary], + fetchContents: [updatedSubscription.fetchContent], + folders: [updatedSubscription.folder], }) return { @@ -237,20 +241,21 @@ export const subscribeResolver = authorized< // limit number of rss subscriptions to max const results = (await getRepository(Subscription).query( - `insert into omnivore.subscriptions (name, url, description, type, user_id, icon, auto_add_to_library, is_private) - select $1, $2, $3, $4, $5, $6, $7, $8 from omnivore.subscriptions + `insert into omnivore.subscriptions (name, url, description, type, user_id, icon, is_private, fetch_content, folder) + select $1, $2, $3, $4, $5, $6, $7, $8, $9 from omnivore.subscriptions where user_id = $5 and type = 'RSS' and status = 'ACTIVE' - having count(*) < $9 + having count(*) < $10 returning *;`, [ feed.title, feed.url, - feed.description || null, + feed.description, SubscriptionType.Rss, uid, - feed.thumbnail || null, - input.autoAddToLibrary ?? null, - input.isPrivate ?? null, + feed.thumbnail, + input.isPrivate, + input.fetchContent ?? true, + input.folder ?? 'following', MAX_RSS_SUBSCRIPTIONS, ] )) as any[] @@ -272,7 +277,8 @@ export const subscribeResolver = authorized< scheduledDates: [new Date()], // fetch immediately fetchedDates: [null], checksums: [null], - addToLibraryFlags: [!!newSubscription.autoAddToLibrary], + fetchContents: [newSubscription.fetchContent], + folders: [newSubscription.folder], }) return { @@ -328,6 +334,8 @@ export const updateSubscriptionResolver = authorized< : undefined, autoAddToLibrary: input.autoAddToLibrary ?? undefined, isPrivate: input.isPrivate ?? undefined, + fetchContent: input.fetchContent ?? undefined, + folder: input.folder ?? undefined, }) return repo.findOneByOrFail({ diff --git a/packages/api/src/routers/svc/rss_feed.ts b/packages/api/src/routers/svc/rss_feed.ts index 595a233ad..065a8406b 100644 --- a/packages/api/src/routers/svc/rss_feed.ts +++ b/packages/api/src/routers/svc/rss_feed.ts @@ -35,7 +35,8 @@ export function rssFeedRouter() { ARRAY_AGG(last_fetched_at) AS "fetchedDates", ARRAY_AGG(coalesce(scheduled_at, NOW())) AS "scheduledDates", ARRAY_AGG(last_fetched_checksum) AS checksums, - ARRAY_AGG(coalesce(auto_add_to_library, false)) AS "addToLibraryFlags" + ARRAY_AGG(fetch_content) AS "fetchContents", + ARRAY_AGG(folder) AS folders FROM omnivore.subscriptions WHERE diff --git a/packages/api/src/schema.ts b/packages/api/src/schema.ts index fc6828362..74b4b3658 100755 --- a/packages/api/src/schema.ts +++ b/packages/api/src/schema.ts @@ -1254,6 +1254,9 @@ const schema = gql` confirmationCode: String createdAt: Date! subscriptionCount: Int! + folder: String! + name: String + description: String } type NewsletterEmailsSuccess { @@ -1266,6 +1269,12 @@ const schema = gql` union NewsletterEmailsResult = NewsletterEmailsSuccess | NewsletterEmailsError + input CreateNewsletterEmailInput { + name: String + description: String + folder: String + } + # Mutation: CreateNewsletterEmail enum CreateNewsletterEmailErrorCode { UNAUTHORIZED @@ -1674,6 +1683,8 @@ const schema = gql` updatedAt: Date isPrivate: Boolean autoAddToLibrary: Boolean + fetchContent: Boolean! + folder: String! } enum SubscriptionStatus { @@ -2577,6 +2588,8 @@ const schema = gql` subscriptionType: SubscriptionType isPrivate: Boolean autoAddToLibrary: Boolean + fetchContent: Boolean + folder: String } input UpdateSubscriptionInput { @@ -2589,6 +2602,8 @@ const schema = gql` scheduledAt: Date isPrivate: Boolean autoAddToLibrary: Boolean + fetchContent: Boolean + folder: String } union UpdateSubscriptionResult = @@ -2753,7 +2768,9 @@ const schema = gql` # input: UpdateLinkShareInfoInput! # ): UpdateLinkShareInfoResult! setLinkArchived(input: ArchiveLinkInput!): ArchiveLinkResult! - createNewsletterEmail: CreateNewsletterEmailResult! + createNewsletterEmail( + input: CreateNewsletterEmailInput + ): CreateNewsletterEmailResult! deleteNewsletterEmail(newsletterEmailId: ID!): DeleteNewsletterEmailResult! saveUrl(input: SaveUrlInput!): SaveResult! savePage(input: SavePageInput!): SaveResult! diff --git a/packages/api/src/services/newsletters.ts b/packages/api/src/services/newsletters.ts index f492cf4b5..e5e382624 100644 --- a/packages/api/src/services/newsletters.ts +++ b/packages/api/src/services/newsletters.ts @@ -19,7 +19,10 @@ const parsedAddress = (emailAddress: string) => { export const createNewsletterEmail = async ( userId: string, - confirmationCode?: string + confirmationCode?: string, + folder?: string, + name?: string, + description?: string ): Promise => { const user = await userRepository.findById(userId) if (!user) { @@ -34,6 +37,9 @@ export const createNewsletterEmail = async ( address: emailAddress, user, confirmationCode, + name, + description, + folder, }) } diff --git a/packages/api/src/services/save_email.ts b/packages/api/src/services/save_email.ts index a2b87ac37..092c2b98f 100644 --- a/packages/api/src/services/save_email.ts +++ b/packages/api/src/services/save_email.ts @@ -34,6 +34,7 @@ export type SaveEmailInput = { unsubHttpUrl?: string newsletterEmailId?: string receivedEmailId: string + folder?: string } const isStubUrl = (url: string): boolean => { @@ -105,6 +106,7 @@ export const saveEmail = async ( siteName: parseResult.parsedContent?.siteName ?? undefined, wordCount: wordsCount(content), subscription: input.author, + folder: input.folder, }, input.userId ) diff --git a/packages/api/src/services/save_newsletter_email.ts b/packages/api/src/services/save_newsletter_email.ts index 9f45c5897..4b6ca70b0 100644 --- a/packages/api/src/services/save_newsletter_email.ts +++ b/packages/api/src/services/save_newsletter_email.ts @@ -1,8 +1,10 @@ import { NewsletterEmail } from '../entity/newsletter_email' +import { Subscription } from '../entity/subscription' import { env } from '../env' import { analytics } from '../utils/analytics' import { logger } from '../utils/logger' import { saveEmail, SaveEmailInput } from './save_email' +import { getSubscriptionByName } from './subscriptions' export interface NewsletterMessage { email: string @@ -20,7 +22,8 @@ export interface NewsletterMessage { // send the push but that is ok and we wont retry in that case. export const saveNewsletter = async ( data: NewsletterMessage, - newsletterEmail: NewsletterEmail + newsletterEmail: NewsletterEmail, + existingSubscription?: Subscription ): Promise => { analytics.track({ userId: newsletterEmail.user.id, @@ -38,6 +41,16 @@ export const saveNewsletter = async ( return false } + // find existing subscription if not provided + if (!existingSubscription) { + existingSubscription = + (await getSubscriptionByName(data.author, newsletterEmail.user.id)) || + undefined + } + + // subscription's folder takes precedence over newsletter email's folder + const folder = existingSubscription?.folder || newsletterEmail.folder + const input: SaveEmailInput = { userId: newsletterEmail.user.id, url: data.url, @@ -48,6 +61,7 @@ export const saveNewsletter = async ( unsubHttpUrl: data.unsubHttpUrl, newsletterEmailId: newsletterEmail.id, receivedEmailId: data.receivedEmailId, + folder, } const savedLibraryItem = await saveEmail(input) if (!savedLibraryItem) { diff --git a/packages/api/src/utils/createTask.ts b/packages/api/src/utils/createTask.ts index cad757348..bbf901e2e 100644 --- a/packages/api/src/utils/createTask.ts +++ b/packages/api/src/utils/createTask.ts @@ -625,7 +625,8 @@ export interface RssSubscriptionGroup { fetchedDates: (Date | null)[] scheduledDates: Date[] checksums: (string | null)[] - addToLibraryFlags: boolean[] + fetchContents: boolean[] + folders: string[] } export const enqueueRssFeedFetch = async ( @@ -643,7 +644,8 @@ export const enqueueRssFeedFetch = async ( timestamp.getTime() ), // unix timestamp in milliseconds userIds: subscriptionGroup.userIds, - addToLibraryFlags: subscriptionGroup.addToLibraryFlags, + fetchContents: subscriptionGroup.fetchContents, + folders: subscriptionGroup.folders, } // If there is no Google Cloud Project Id exposed, it means that we are in local environment diff --git a/packages/db/migrations/0149.do.add_fetch_content_to_subscriptions.sql b/packages/db/migrations/0149.do.add_fetch_content_to_subscriptions.sql new file mode 100755 index 000000000..66bd1f373 --- /dev/null +++ b/packages/db/migrations/0149.do.add_fetch_content_to_subscriptions.sql @@ -0,0 +1,16 @@ +-- Type: DO +-- Name: add_fetch_content_to_subscriptions +-- Description: Add fetch_content column to subscriptions tables + +BEGIN; + +ALTER TABLE omnivore.subscriptions + ADD COLUMN fetch_content BOOLEAN NOT NULL DEFAULT TRUE, + ADD COLUMN folder TEXT NOT NULL DEFAULT 'following'; + +ALTER TABLE omnivore.newsletter_emails + ADD COLUMN name TEXT, + ADD COLUMN description TEXT, + ADD COLUMN folder TEXT NOT NULL DEFAULT 'inbox'; + +COMMIT; diff --git a/packages/db/migrations/0149.undo.add_fetch_content_to_subscriptions.sql b/packages/db/migrations/0149.undo.add_fetch_content_to_subscriptions.sql new file mode 100755 index 000000000..5fad9146c --- /dev/null +++ b/packages/db/migrations/0149.undo.add_fetch_content_to_subscriptions.sql @@ -0,0 +1,16 @@ +-- Type: UNDO +-- Name: add_fetch_content_to_subscriptions +-- Description: Add fetch_content column to subscriptions tables + +BEGIN; + +ALTER TABLE omnivore.subscriptions + DROP COLUMN fetch_content, + DROP COLUMN folder; + +ALTER TABLE omnivore.newsletter_emails + DROP COLUMN name, + DROP COLUMN description, + DROP COLUMN folder; + +COMMIT; diff --git a/packages/rss-handler/src/index.ts b/packages/rss-handler/src/index.ts index f80d99726..0b7ed7dab 100644 --- a/packages/rss-handler/src/index.ts +++ b/packages/rss-handler/src/index.ts @@ -8,6 +8,8 @@ import Parser, { Item } from 'rss-parser' import { promisify } from 'util' import { CONTENT_FETCH_URL, createCloudTask } from './task' +type FolderType = 'following' | 'inbox' + interface RssFeedRequest { subscriptionIds: string[] feedUrl: string @@ -15,7 +17,8 @@ interface RssFeedRequest { scheduledTimestamps: number[] // unix timestamp in milliseconds lastFetchedChecksums: string[] userIds: string[] - addToLibraryFlags: boolean[] + fetchContents: boolean[] + folders: FolderType[] } // link can be a string or an object @@ -58,7 +61,8 @@ function isRssFeedRequest(body: any): body is RssFeedRequest { 'scheduledTimestamps' in body && 'userIds' in body && 'lastFetchedChecksums' in body && - 'addToLibraryFlags' in body + 'fetchContents' in body && + 'folders' in body ) } @@ -198,13 +202,17 @@ const createTask = async ( userId: string, feedUrl: string, item: RssFeedItem, - autoAddToLibrary: boolean + fetchContent: boolean, + folder: FolderType ) => { - const folder = autoAddToLibrary ? 'inbox' : 'following' - return createSavingItemTask(userId, feedUrl, item, folder) + if (folder === 'following' && !fetchContent) { + return createItemWithPreviewContent(userId, feedUrl, item) + } + + return fetchContentAndCreateItem(userId, feedUrl, item, folder) } -const createSavingItemTask = async ( +const fetchContentAndCreateItem = async ( userId: string, feedUrl: string, item: RssFeedItem, @@ -235,7 +243,7 @@ const createSavingItemTask = async ( } } -const createFollowingTask = async ( +const createItemWithPreviewContent = async ( userId: string, feedUrl: string, item: RssFeedItem @@ -247,7 +255,7 @@ const createFollowingTask = async ( author: item.creator, description: item.summary, addedToFollowingFrom: 'feed', - previewContent: item.content || item.contentSnippet, + previewContent: item.content || item.contentSnippet || item.summary, addedToFollowingBy: feedUrl, savedAt: item.isoDate, publishedAt: item.isoDate, @@ -372,7 +380,8 @@ const processSubscription = async ( lastFetchedAt: number, scheduledAt: number, lastFetchedChecksum: string, - autoAddToLibrary: boolean, + fetchContent: boolean, + folder: FolderType, feed: RssFeed ) => { let lastItemFetchedAt: Date | null = null @@ -440,7 +449,13 @@ const processSubscription = async ( continue } - const created = await createTask(userId, feedUrl, item, autoAddToLibrary) + const created = await createTask( + userId, + feedUrl, + item, + fetchContent, + folder + ) if (!created) { console.error('Failed to create task for feed item', item.link) continue @@ -467,7 +482,8 @@ const processSubscription = async ( userId, feedUrl, lastValidItem, - autoAddToLibrary + fetchContent, + folder ) if (!created) { console.error('Failed to create task for feed item', lastValidItem.link) @@ -514,7 +530,8 @@ export const rssHandler = Sentry.GCPFunction.wrapHttpFunction( scheduledTimestamps, userIds, lastFetchedChecksums, - addToLibraryFlags, + fetchContents, + folders, } = req.body console.log('Processing feed', feedUrl) @@ -537,7 +554,8 @@ export const rssHandler = Sentry.GCPFunction.wrapHttpFunction( lastFetchedTimestamps[i], scheduledTimestamps[i], lastFetchedChecksums[i], - addToLibraryFlags[i], + fetchContents[i], + folders[i], feed ) )