Skip to content

Commit

Permalink
Rate limiting
Browse files Browse the repository at this point in the history
  • Loading branch information
samselikoff committed Nov 12, 2024
1 parent 4ced83f commit d57286c
Show file tree
Hide file tree
Showing 14 changed files with 606 additions and 172 deletions.
68 changes: 35 additions & 33 deletions app/api/generate-logo/route.ts
Original file line number Diff line number Diff line change
@@ -1,22 +1,23 @@
import dedent from "dedent";
import Together from "together-ai";
import { z } from "zod";
// import { Ratelimit } from "@upstash/ratelimit";
// import { Redis } from "@upstash/redis";
import { Ratelimit } from "@upstash/ratelimit";
import { Redis } from "@upstash/redis";
import { headers } from "next/headers";
// import { headers } from "next/headers";

// let ratelimit: Ratelimit | undefined;
let ratelimit: Ratelimit | undefined;

// Add rate limiting if Upstash API keys are set, otherwise skip
// if (process.env.UPSTASH_REDIS_REST_URL) {
// ratelimit = new Ratelimit({
// redis: Redis.fromEnv(),
// // Allow 100 requests per day (~5-10 prompts)
// limiter: Ratelimit.fixedWindow(100, "1440 m"),
// analytics: true,
// prefix: "blinkshot",
// });
// }
if (process.env.UPSTASH_REDIS_REST_URL) {
ratelimit = new Ratelimit({
redis: Redis.fromEnv(),
// Allow 100 requests per day (~5-10 prompts)
limiter: Ratelimit.fixedWindow(2, "1440 m"),
analytics: true,
prefix: "logocreator",
});
}

export async function POST(req: Request) {
const json = await req.json();
Expand Down Expand Up @@ -47,19 +48,20 @@ export async function POST(req: Request) {
// client.apiKey = userAPIKey;
// }

// if (ratelimit && !userAPIKey) {
// const identifier = getIPAddress();

// const { success } = await ratelimit.limit(identifier);
// if (!success) {
// return Response.json(
// "No requests left. Please add your own API key or try again in 24h.",
// {
// status: 429,
// },
// );
// }
// }
if (ratelimit) {
const identifier = getIPAddress();
console.log(identifier);

const { success } = await ratelimit.limit(identifier);
if (!success) {
return Response.json(
"No requests left. Please add your own API key or try again in 24h.",
{
status: 429,
},
);
}
}

const prompt = dedent`Design a professional, unique, and memorable logo for a company that effectively represents the brand's identity and values. The logo should be versatile for use across various mediums and sizes, maintaining clarity and impact in both digital and print formats.
Expand Down Expand Up @@ -120,13 +122,13 @@ export async function POST(req: Request) {

export const runtime = "edge";

// function getIPAddress() {
// const FALLBACK_IP_ADDRESS = '0.0.0.0';
// const forwardedFor = headers().get('x-forwarded-for');
function getIPAddress() {
const FALLBACK_IP_ADDRESS = "0.0.0.0";
const forwardedFor = headers().get("x-forwarded-for");

// if (forwardedFor) {
// return forwardedFor.split(',')[0] ?? FALLBACK_IP_ADDRESS;
// }
if (forwardedFor) {
return forwardedFor.split(",")[0] ?? FALLBACK_IP_ADDRESS;
}

// return headers().get('x-real-ip') ?? FALLBACK_IP_ADDRESS;
// }
return headers().get("x-real-ip") ?? FALLBACK_IP_ADDRESS;
}
12 changes: 6 additions & 6 deletions app/components/Header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,26 +9,26 @@ interface HeaderProps {
const Header: React.FC<HeaderProps> = ({ className }) => {
return (
<header className={`w-full ${className}`}>
<div className="flex items-center justify-between px-4 py-2 bg-[#343434] md:mt-4">
<div className="flex items-center justify-between bg-[#343434] px-4 py-2 md:mt-4">
{/* Logo - left on mobile, centered on larger screens */}
<div className="flex-grow flex justify-start md:justify-center">
<div className="flex flex-grow justify-start md:justify-center">
<Link href="https://www.together.ai" className="flex items-center">
<Image
src="together-ai-logo1.svg"
alt="together.ai"
width={450}
height={120}
className="w-[233px] md:w-[350px] lg:w-[450px] pl-0 lg:pl-28"
className="w-[233px] pl-0 md:w-[350px] lg:w-[450px] lg:pl-28"
/>
</Link>
</div>
{/* Credits Section */}
<div className="flex items-center space-x-2">
<div className="flex items-center">
<span className="text-sm text-gray-400 hidden lg:block">
<span className="hidden text-sm text-gray-400 lg:block">
Credits:
</span>
<span className="text-sm font-jura text-gray-300 hidden lg:block ml-0.5">
<span className="ml-0.5 hidden text-sm text-gray-300 lg:block">
3
</span>
</div>
Expand All @@ -37,7 +37,7 @@ const Header: React.FC<HeaderProps> = ({ className }) => {
alt="Insan"
width={36}
height={36}
className="w-8 h-8 md:w-9 md:h-9 bg-gray-600 rounded-full border border-black"
className="h-8 w-8 rounded-full border border-black bg-gray-600 md:h-9 md:w-9"
/>
</div>
</div>
Expand Down
2 changes: 1 addition & 1 deletion app/components/LogoPlaceholder.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import React from "react";

const LogoPlaceholder = () => (
<div className="m-4 flex aspect-square w-full flex-col items-center justify-center rounded-xl bg-[#2C2C2C] sm:m-0 md:m-4">
<h4 className="text-center font-jura text-base leading-tight text-white">
<h4 className="text-center text-base leading-tight text-white">
Generate your dream
<br />
logo in 10 seconds!
Expand Down
10 changes: 5 additions & 5 deletions app/components/footer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ import TwitterSVG from "../../public/twitter.svg";
import GithubSVG from "../../public/Github.svg";
import Image from "next/image";
const Footer = () => (
<div className="flex flex-col md:flex-row justify-between items-center px-4 py-4 bg-[#343434] font-Jura">
<div className="flex-grow text-center mb-2 md:mb-0 pl-0 md:pl-0 lg:pl-48">
<div className="flex flex-col items-center justify-between bg-[#343434] px-4 py-4 md:flex-row">
<div className="mb-2 flex-grow pl-0 text-center md:mb-0 md:pl-0 lg:pl-48">
<span className="text-sm text-[#6F6F6F]">
Powered by{" "}
<a href="https://www.together.ai/" className="underline">
Expand All @@ -19,17 +19,17 @@ const Footer = () => (
</a>
</span>
</div>
<div className="flex space-x-3 mb-2 md:mb-0">
<div className="mb-2 flex space-x-3 md:mb-0">
<a
href="https://github.com/Nutlope"
className="text-sm text-[#6F6F6F] px-2 py-1 border border-[#6F6F6F] rounded flex items-center"
className="flex items-center rounded border border-[#6F6F6F] px-2 py-1 text-sm text-[#6F6F6F]"
>
<Image src={GithubSVG} alt="Twitter" className="mr-1 h-5 w-5" />
Github
</a>
<a
href="https://x.com/nutlope"
className="text-sm text-[#6F6F6F] px-2 py-1 border border-[#6F6F6F] rounded flex items-center"
className="flex items-center rounded border border-[#6F6F6F] px-2 py-1 text-sm text-[#6F6F6F]"
>
<Image src={TwitterSVG} alt="github" className="mr-1 h-4 w-4" />
Twitter
Expand Down
129 changes: 129 additions & 0 deletions app/components/ui/toast.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
"use client";

import * as React from "react";
import * as ToastPrimitives from "@radix-ui/react-toast";
import { cva, type VariantProps } from "class-variance-authority";
import { X } from "lucide-react";

import { cn } from "@/lib/utils";

const ToastProvider = ToastPrimitives.Provider;

const ToastViewport = React.forwardRef<
React.ElementRef<typeof ToastPrimitives.Viewport>,
React.ComponentPropsWithoutRef<typeof ToastPrimitives.Viewport>
>(({ className, ...props }, ref) => (
<ToastPrimitives.Viewport
ref={ref}
className={cn(
"fixed top-0 z-[100] flex max-h-screen w-full flex-col-reverse p-4 sm:right-0 sm:flex-col md:max-w-[420px]",
className,
)}
{...props}
/>
));
ToastViewport.displayName = ToastPrimitives.Viewport.displayName;

const toastVariants = cva(
"group pointer-events-auto relative flex w-full items-center justify-between space-x-2 overflow-hidden rounded-md border p-4 pr-6 shadow-lg transition-all data-[swipe=cancel]:translate-x-0 data-[swipe=end]:translate-x-[var(--radix-toast-swipe-end-x)] data-[swipe=move]:translate-x-[var(--radix-toast-swipe-move-x)] data-[swipe=move]:transition-none data-[state=open]:animate-in data-[state=closed]:animate-out data-[swipe=end]:animate-out data-[state=closed]:fade-out-80 data-[state=closed]:slide-out-to-right-full data-[state=open]:slide-in-from-top-full",
{
variants: {
variant: {
default: "border bg-background text-foreground",
destructive:
"destructive group border-destructive bg-destructive text-destructive-foreground",
},
},
defaultVariants: {
variant: "default",
},
},
);

const Toast = React.forwardRef<
React.ElementRef<typeof ToastPrimitives.Root>,
React.ComponentPropsWithoutRef<typeof ToastPrimitives.Root> &
VariantProps<typeof toastVariants>
>(({ className, variant, ...props }, ref) => {
return (
<ToastPrimitives.Root
ref={ref}
className={cn(toastVariants({ variant }), className)}
{...props}
/>
);
});
Toast.displayName = ToastPrimitives.Root.displayName;

const ToastAction = React.forwardRef<
React.ElementRef<typeof ToastPrimitives.Action>,
React.ComponentPropsWithoutRef<typeof ToastPrimitives.Action>
>(({ className, ...props }, ref) => (
<ToastPrimitives.Action
ref={ref}
className={cn(
"inline-flex h-8 shrink-0 items-center justify-center rounded-md border bg-transparent px-3 text-sm font-medium transition-colors hover:bg-secondary focus:outline-none focus:ring-1 focus:ring-ring disabled:pointer-events-none disabled:opacity-50 group-[.destructive]:border-muted/40 group-[.destructive]:hover:border-destructive/30 group-[.destructive]:hover:bg-destructive group-[.destructive]:hover:text-destructive-foreground group-[.destructive]:focus:ring-destructive",
className,
)}
{...props}
/>
));
ToastAction.displayName = ToastPrimitives.Action.displayName;

const ToastClose = React.forwardRef<
React.ElementRef<typeof ToastPrimitives.Close>,
React.ComponentPropsWithoutRef<typeof ToastPrimitives.Close>
>(({ className, ...props }, ref) => (
<ToastPrimitives.Close
ref={ref}
className={cn(
"absolute right-1 top-1 rounded-md p-1 text-foreground/50 opacity-0 transition-opacity hover:text-foreground focus:opacity-100 focus:outline-none focus:ring-1 group-hover:opacity-100 group-[.destructive]:text-red-300 group-[.destructive]:hover:text-red-50 group-[.destructive]:focus:ring-red-400 group-[.destructive]:focus:ring-offset-red-600",
className,
)}
toast-close=""
{...props}
>
<X className="h-4 w-4" />
</ToastPrimitives.Close>
));
ToastClose.displayName = ToastPrimitives.Close.displayName;

const ToastTitle = React.forwardRef<
React.ElementRef<typeof ToastPrimitives.Title>,
React.ComponentPropsWithoutRef<typeof ToastPrimitives.Title>
>(({ className, ...props }, ref) => (
<ToastPrimitives.Title
ref={ref}
className={cn("text-sm font-semibold [&+div]:text-xs", className)}
{...props}
/>
));
ToastTitle.displayName = ToastPrimitives.Title.displayName;

const ToastDescription = React.forwardRef<
React.ElementRef<typeof ToastPrimitives.Description>,
React.ComponentPropsWithoutRef<typeof ToastPrimitives.Description>
>(({ className, ...props }, ref) => (
<ToastPrimitives.Description
ref={ref}
className={cn("text-sm opacity-90", className)}
{...props}
/>
));
ToastDescription.displayName = ToastPrimitives.Description.displayName;

type ToastProps = React.ComponentPropsWithoutRef<typeof Toast>;

type ToastActionElement = React.ReactElement<typeof ToastAction>;

export {
type ToastProps,
type ToastActionElement,
ToastProvider,
ToastViewport,
Toast,
ToastTitle,
ToastDescription,
ToastClose,
ToastAction,
};
35 changes: 35 additions & 0 deletions app/components/ui/toaster.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
"use client"

import { useToast } from "@/hooks/use-toast"
import {
Toast,
ToastClose,
ToastDescription,
ToastProvider,
ToastTitle,
ToastViewport,
} from "@/components/ui/toast"

export function Toaster() {
const { toasts } = useToast()

return (
<ToastProvider>
{toasts.map(function ({ id, title, description, action, ...props }) {
return (
<Toast key={id} {...props}>
<div className="grid gap-1">
{title && <ToastTitle>{title}</ToastTitle>}
{description && (
<ToastDescription>{description}</ToastDescription>
)}
</div>
{action}
<ToastClose />
</Toast>
)
})}
<ToastViewport />
</ToastProvider>
)
}
4 changes: 2 additions & 2 deletions app/components/ui/tooltip.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@ const TooltipContent = React.forwardRef<
ref={ref}
sideOffset={sideOffset}
className={cn(
"z-50 overflow-hidden rounded-md font-jura font-light bg-gray-700 px-3 py-1.5 text-xs text-gray-200 shadow-md animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
className
"z-50 overflow-hidden rounded-md bg-gray-700 px-3 py-1.5 text-xs font-light text-gray-200 shadow-md animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
className,
)}
{...props}
/>
Expand Down
Loading

0 comments on commit d57286c

Please sign in to comment.