From e96782baab087cccc86a125f219a7da5b7ef54ef Mon Sep 17 00:00:00 2001 From: Huang Xin Date: Sat, 22 Feb 2025 09:09:25 +0100 Subject: [PATCH] api: load balance of the API keys for deepl translate, closes #429 (#431) --- apps/readest-app/.env.local.example | 4 ++-- .../readest-app/src/pages/api/deepl/translate.ts | 16 ++++++++++++++-- apps/readest-app/src/utils/access.ts | 5 +++++ 3 files changed, 21 insertions(+), 4 deletions(-) diff --git a/apps/readest-app/.env.local.example b/apps/readest-app/.env.local.example index 3ada9deb..9f4102f2 100644 --- a/apps/readest-app/.env.local.example +++ b/apps/readest-app/.env.local.example @@ -4,8 +4,8 @@ NEXT_PUBLIC_POSTHOG_HOST=YOUR_POSTHOG_HOST NEXT_PUBLIC_SUPABASE_URL=YOUR_SUPABASE_URL NEXT_PUBLIC_SUPABASE_ANON_KEY=YOUR_SUPABASE_ANON_KEY -DEEPL_PRO_API_KEY=YOUR_DEEPL_PRO_API_KEY -DEEPL_FREE_API_KEY=YOUR_DEEPL_FREE_API_KEY +DEEPL_PRO_API_KEYS=YOUR_DEEPL_PRO_API_KEYS +DEEPL_FREE_API_KEYS=YOUR_DEEPL_FREE_API_KEYS R2_TOKEN_VALUE=YOUR_R2_TOKEN_VALUE R2_ACCESS_KEY_ID=YOUR_R2_ACCESS_KEY_ID diff --git a/apps/readest-app/src/pages/api/deepl/translate.ts b/apps/readest-app/src/pages/api/deepl/translate.ts index d3f8a5ed..2445355d 100644 --- a/apps/readest-app/src/pages/api/deepl/translate.ts +++ b/apps/readest-app/src/pages/api/deepl/translate.ts @@ -1,6 +1,7 @@ import { NextApiRequest, NextApiResponse } from 'next'; import { corsAllMethods, runMiddleware } from '@/utils/cors'; import { supabase } from '@/utils/supabase'; +import { getUserPlan } from '@/utils/access'; const DEEPL_FREE_API = 'https://api-free.deepl.com/v2/translate'; const DEEPL_PRO_API = 'https://api.deepl.com/v2/translate'; @@ -18,11 +19,22 @@ const getUserAndToken = async (authHeader: string | undefined) => { return { user, token }; }; +const getDeepLAPIKey = (keys: string | undefined) => { + const keyArray = keys?.split(',') ?? []; + return keyArray[Math.floor(Math.random() * keyArray.length)]; +}; + const handler = async (req: NextApiRequest, res: NextApiResponse) => { const { user, token } = await getUserAndToken(req.headers['authorization']); - const deeplApiUrl = user && token ? DEEPL_PRO_API : DEEPL_FREE_API; + let deeplApiUrl = DEEPL_FREE_API; + if (user && token) { + const userPlan = await getUserPlan(token); + if (userPlan !== 'free') deeplApiUrl = DEEPL_PRO_API; + } const deeplAuthKey = - user && token ? process.env['DEEPL_PRO_API_KEY'] : process.env['DEEPL_FREE_API_KEY']; + deeplApiUrl === DEEPL_PRO_API + ? getDeepLAPIKey(process.env['DEEPL_PRO_API_KEYS']) + : getDeepLAPIKey(process.env['DEEPL_FREE_API_KEYS']); await runMiddleware(req, res, corsAllMethods); diff --git a/apps/readest-app/src/utils/access.ts b/apps/readest-app/src/utils/access.ts index fe46ff1d..8f2df135 100644 --- a/apps/readest-app/src/utils/access.ts +++ b/apps/readest-app/src/utils/access.ts @@ -10,6 +10,11 @@ interface Token { [key: string]: string | number; } +export const getUserPlan = async (token: string): Promise => { + const data = jwtDecode(token) || {}; + return data['plan'] || 'free'; +}; + export const getStoragePlanData = (token: string) => { const data = jwtDecode(token) || {}; const plan = data['plan'] || 'free';