Support screenshot by URL for all paying customers

This commit is contained in:
Abi Raja 2024-01-30 14:32:57 -05:00
parent e9140c331b
commit ab15aff021
3 changed files with 45 additions and 12 deletions

View File

@ -11,4 +11,7 @@ SHOULD_MOCK_AI_RESPONSE = bool(os.environ.get("MOCK", False))
IS_PROD = os.environ.get("IS_PROD", False) IS_PROD = os.environ.get("IS_PROD", False)
# Hosted version only # Hosted version only
PLATFORM_SCREENSHOTONE_API_KEY = os.environ.get("PLATFORM_SCREENSHOTONE_API_KEY", "")
BACKEND_SAAS_URL = os.environ.get("BACKEND_SAAS_URL", "") BACKEND_SAAS_URL = os.environ.get("BACKEND_SAAS_URL", "")

View File

@ -2,6 +2,9 @@ import base64
from fastapi import APIRouter from fastapi import APIRouter
from pydantic import BaseModel from pydantic import BaseModel
import httpx import httpx
from config import PLATFORM_SCREENSHOTONE_API_KEY
from routes.saas_utils import does_user_have_subscription_credits
router = APIRouter() router = APIRouter()
@ -12,10 +15,30 @@ def bytes_to_data_url(image_bytes: bytes, mime_type: str) -> str:
async def capture_screenshot( async def capture_screenshot(
target_url: str, api_key: str, device: str = "desktop" target_url: str, api_key: str | None, auth_token: str, device: str = "desktop"
) -> bytes: ) -> bytes:
api_base_url = "https://api.screenshotone.com/take" api_base_url = "https://api.screenshotone.com/take"
# Get auth token
if not auth_token:
raise Exception("No auth token with capture_screenshot")
# If API key is not passed in, only use the platform ScreenshotOne API key if the user is a subscriber
if not api_key:
res = await does_user_have_subscription_credits(auth_token)
if res.status == "not_subscriber":
raise Exception(
"capture_screenshot - User is not subscriber and has no API key"
)
elif res.status == "subscriber_has_credits":
api_key = PLATFORM_SCREENSHOTONE_API_KEY
elif res.status == "subscriber_has_no_credits":
raise Exception("capture_screenshot - User has no credits")
else:
raise Exception(
"capture_screenshot - Unknown error occurred when checking subscription credits"
)
params = { params = {
"access_key": api_key, "access_key": api_key,
"url": target_url, "url": target_url,
@ -44,7 +67,8 @@ async def capture_screenshot(
class ScreenshotRequest(BaseModel): class ScreenshotRequest(BaseModel):
url: str url: str
apiKey: str apiKey: str | None
authToken: str
class ScreenshotResponse(BaseModel): class ScreenshotResponse(BaseModel):
@ -56,9 +80,10 @@ async def app_screenshot(request: ScreenshotRequest):
# Extract the URL from the request body # Extract the URL from the request body
url = request.url url = request.url
api_key = request.apiKey api_key = request.apiKey
auth_token = request.authToken
# TODO: Add error handling # TODO: Add error handling
image_bytes = await capture_screenshot(url, api_key=api_key) image_bytes = await capture_screenshot(url, api_key=api_key, auth_token=auth_token)
# Convert the image bytes to a data url # Convert the image bytes to a data url
data_url = bytes_to_data_url(image_bytes, "image/png") data_url = bytes_to_data_url(image_bytes, "image/png")

View File

@ -3,6 +3,8 @@ import { HTTP_BACKEND_URL } from "../config";
import { Button } from "./ui/button"; import { Button } from "./ui/button";
import { Input } from "./ui/input"; import { Input } from "./ui/input";
import { toast } from "react-hot-toast"; import { toast } from "react-hot-toast";
import { useStore } from "../store/store";
import { useAuth } from "@clerk/clerk-react";
interface Props { interface Props {
screenshotOneApiKey: string | null; screenshotOneApiKey: string | null;
@ -13,28 +15,31 @@ export function UrlInputSection({ doCreate, screenshotOneApiKey }: Props) {
const [isLoading, setIsLoading] = useState(false); const [isLoading, setIsLoading] = useState(false);
const [referenceUrl, setReferenceUrl] = useState(""); const [referenceUrl, setReferenceUrl] = useState("");
// Hosted version only
const subscriberTier = useStore((state) => state.subscriberTier);
const { getToken } = useAuth();
async function takeScreenshot() { async function takeScreenshot() {
if (!screenshotOneApiKey) { if (!referenceUrl) {
toast.error( return toast.error("Please enter a URL");
"Please add a ScreenshotOne API key in the Settings dialog. This is optional - you can also drag/drop and upload images directly.",
{ duration: 8000 }
);
return;
} }
if (!referenceUrl) { if (!screenshotOneApiKey && subscriberTier === "free") {
toast.error("Please enter a URL"); return toast.error(
return; "Please upgrade to a paid plan to use the screenshot feature."
);
} }
if (referenceUrl) { if (referenceUrl) {
try { try {
setIsLoading(true); setIsLoading(true);
const authToken = await getToken();
const response = await fetch(`${HTTP_BACKEND_URL}/api/screenshot`, { const response = await fetch(`${HTTP_BACKEND_URL}/api/screenshot`, {
method: "POST", method: "POST",
body: JSON.stringify({ body: JSON.stringify({
url: referenceUrl, url: referenceUrl,
apiKey: screenshotOneApiKey, apiKey: screenshotOneApiKey,
authToken,
}), }),
headers: { headers: {
"Content-Type": "application/json", "Content-Type": "application/json",