From 21d4efc2b531c7c417f0ae259f12c6d661c43543 Mon Sep 17 00:00:00 2001 From: Jackson Harper Date: Mon, 18 Mar 2024 13:56:37 +0800 Subject: [PATCH 1/2] Allow opting into the YouTube transcript feature --- packages/api/src/services/features.ts | 32 ++++++++++++++++++++------- 1 file changed, 24 insertions(+), 8 deletions(-) diff --git a/packages/api/src/services/features.ts b/packages/api/src/services/features.ts index f362d6b56..ebb87eaaa 100644 --- a/packages/api/src/services/features.ts +++ b/packages/api/src/services/features.ts @@ -6,6 +6,9 @@ import { env } from '../env' import { getRepository } from '../repository' import { logger } from '../utils/logger' +const MAX_ULTRA_REALISTIC_USERS = 1500 +const MAX_YOUTUBE_TRANSCRIPT_USERS = 100 + export enum FeatureName { AISummaries = 'ai-summaries', YouTubeTranscripts = 'youtube-transcripts', @@ -20,16 +23,31 @@ export const optInFeature = async ( name: FeatureName, uid: string ): Promise => { - if (name === FeatureName.UltraRealisticVoice) { - return optInUltraRealisticVoice(uid) + switch (name) { + case FeatureName.UltraRealisticVoice: + return optInLimitedFeature( + FeatureName.UltraRealisticVoice, + uid, + MAX_ULTRA_REALISTIC_USERS + ) + case FeatureName.YouTubeTranscripts: + return optInLimitedFeature( + FeatureName.YouTubeTranscripts, + uid, + MAX_YOUTUBE_TRANSCRIPT_USERS + ) } return undefined } -const optInUltraRealisticVoice = async (uid: string): Promise => { +const optInLimitedFeature = async ( + featureName: string, + uid: string, + maxUsers: number +): Promise => { const feature = await getRepository(Feature).findOne({ where: { - name: FeatureName.UltraRealisticVoice, + name: featureName, grantedAt: Not(IsNull()), user: { id: uid }, }, @@ -41,8 +59,6 @@ const optInUltraRealisticVoice = async (uid: string): Promise => { return feature } - const MAX_USERS = 1500 - // opt in to feature for the first 1500 users const optedInFeatures = (await appDataSource.query( `insert into omnivore.features (user_id, name, granted_at) select $1, $2, $3 from omnivore.features @@ -51,7 +67,7 @@ const optInUltraRealisticVoice = async (uid: string): Promise => { on conflict (user_id, name) do update set granted_at = $3 returning *, granted_at as "grantedAt", created_at as "createdAt", updated_at as "updatedAt";`, - [uid, FeatureName.UltraRealisticVoice, new Date(), MAX_USERS] + [uid, featureName, new Date(), maxUsers] )) as Feature[] // if no new features were created then user has exceeded max users @@ -61,7 +77,7 @@ const optInUltraRealisticVoice = async (uid: string): Promise => { // create/update an opt-in record with null grantedAt const optInRecord = { user: { id: uid }, - name: FeatureName.UltraRealisticVoice, + name: featureName, grantedAt: null, } const result = await getRepository(Feature).upsert(optInRecord, [ From 10bd05c6a89156b96b113b5ef389b1673ac9330d Mon Sep 17 00:00:00 2001 From: Jackson Harper Date: Mon, 18 Mar 2024 15:00:12 +0800 Subject: [PATCH 2/2] Allow opt into transcripts feature, create UI --- packages/web/lib/networking/queries/useGetViewerQuery.tsx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/web/lib/networking/queries/useGetViewerQuery.tsx b/packages/web/lib/networking/queries/useGetViewerQuery.tsx index 88beccd8b..abf88c1ff 100644 --- a/packages/web/lib/networking/queries/useGetViewerQuery.tsx +++ b/packages/web/lib/networking/queries/useGetViewerQuery.tsx @@ -3,6 +3,7 @@ import useSWR from 'swr' import { publicGqlFetcher } from '../networkHelpers' type ViewerQueryResponse = { + mutate: () => void viewerData?: ViewerQueryResponseData viewerDataError?: unknown isLoading: boolean @@ -51,9 +52,10 @@ export function useGetViewerQuery(): ViewerQueryResponse { } ` - const { data, error } = useSWR(query, publicGqlFetcher) + const { data, error, mutate } = useSWR(query, publicGqlFetcher) return { + mutate, viewerData: data as ViewerQueryResponseData, viewerDataError: error, // TODO: figure out error possibilities isLoading: !error && !data,