Spaces:
Running
Running
add pro subs if limit has been reached
Browse files
server.js
CHANGED
@@ -31,7 +31,7 @@ const PORT = process.env.APP_PORT || 3000;
|
|
31 |
const REDIRECT_URI =
|
32 |
process.env.REDIRECT_URI || `http://localhost:${PORT}/auth/login`;
|
33 |
const MODEL_ID = "deepseek-ai/DeepSeek-V3-0324";
|
34 |
-
const MAX_REQUESTS_PER_IP =
|
35 |
|
36 |
app.use(cookieParser());
|
37 |
app.use(bodyParser.json());
|
@@ -325,6 +325,13 @@ app.post("/api/ask-ai", async (req, res) => {
|
|
325 |
// End the response stream
|
326 |
res.end();
|
327 |
} catch (error) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
328 |
if (!res.headersSent) {
|
329 |
res.status(500).send({
|
330 |
ok: false,
|
@@ -349,8 +356,6 @@ app.get("/api/remix/:username/:repo", async (req, res) => {
|
|
349 |
name: repoId,
|
350 |
});
|
351 |
|
352 |
-
console.log(space);
|
353 |
-
|
354 |
if (!space || space.sdk !== "static" || space.private) {
|
355 |
return res.status(404).send({
|
356 |
ok: false,
|
|
|
31 |
const REDIRECT_URI =
|
32 |
process.env.REDIRECT_URI || `http://localhost:${PORT}/auth/login`;
|
33 |
const MODEL_ID = "deepseek-ai/DeepSeek-V3-0324";
|
34 |
+
const MAX_REQUESTS_PER_IP = 2;
|
35 |
|
36 |
app.use(cookieParser());
|
37 |
app.use(bodyParser.json());
|
|
|
325 |
// End the response stream
|
326 |
res.end();
|
327 |
} catch (error) {
|
328 |
+
if (error.message.includes("exceeded your monthly included credits")) {
|
329 |
+
return res.status(402).send({
|
330 |
+
ok: false,
|
331 |
+
openProModal: true,
|
332 |
+
message: error.message,
|
333 |
+
});
|
334 |
+
}
|
335 |
if (!res.headersSent) {
|
336 |
res.status(500).send({
|
337 |
ok: false,
|
|
|
356 |
name: repoId,
|
357 |
});
|
358 |
|
|
|
|
|
359 |
if (!space || space.sdk !== "static" || space.private) {
|
360 |
return res.status(404).send({
|
361 |
ok: false,
|
src/components/ask-ai/ask-ai.tsx
CHANGED
@@ -11,6 +11,7 @@ import Login from "../login/login";
|
|
11 |
import { defaultHTML } from "./../../../utils/consts";
|
12 |
import SuccessSound from "./../../assets/success.mp3";
|
13 |
import Settings from "../settings/settings";
|
|
|
14 |
// import SpeechPrompt from "../speech-prompt/speech-prompt";
|
15 |
|
16 |
function AskAI({
|
@@ -35,6 +36,7 @@ function AskAI({
|
|
35 |
const [provider, setProvider] = useLocalStorage("provider", "auto");
|
36 |
const [openProvider, setOpenProvider] = useState(false);
|
37 |
const [providerError, setProviderError] = useState("");
|
|
|
38 |
|
39 |
const audio = new Audio(SuccessSound);
|
40 |
audio.volume = 0.5;
|
@@ -67,6 +69,8 @@ function AskAI({
|
|
67 |
} else if (res.openSelectProvider) {
|
68 |
setOpenProvider(true);
|
69 |
setProviderError(res.message);
|
|
|
|
|
70 |
} else {
|
71 |
toast.error(res.message);
|
72 |
}
|
@@ -208,6 +212,11 @@ function AskAI({
|
|
208 |
</p>
|
209 |
</Login>
|
210 |
</div>
|
|
|
|
|
|
|
|
|
|
|
211 |
</div>
|
212 |
);
|
213 |
}
|
|
|
11 |
import { defaultHTML } from "./../../../utils/consts";
|
12 |
import SuccessSound from "./../../assets/success.mp3";
|
13 |
import Settings from "../settings/settings";
|
14 |
+
import ProModal from "../pro-modal/pro-modal";
|
15 |
// import SpeechPrompt from "../speech-prompt/speech-prompt";
|
16 |
|
17 |
function AskAI({
|
|
|
36 |
const [provider, setProvider] = useLocalStorage("provider", "auto");
|
37 |
const [openProvider, setOpenProvider] = useState(false);
|
38 |
const [providerError, setProviderError] = useState("");
|
39 |
+
const [openProModal, setOpenProModal] = useState(false);
|
40 |
|
41 |
const audio = new Audio(SuccessSound);
|
42 |
audio.volume = 0.5;
|
|
|
69 |
} else if (res.openSelectProvider) {
|
70 |
setOpenProvider(true);
|
71 |
setProviderError(res.message);
|
72 |
+
} else if (res.openProModal) {
|
73 |
+
setOpenProModal(true);
|
74 |
} else {
|
75 |
toast.error(res.message);
|
76 |
}
|
|
|
212 |
</p>
|
213 |
</Login>
|
214 |
</div>
|
215 |
+
<ProModal
|
216 |
+
html={html}
|
217 |
+
open={openProModal}
|
218 |
+
onClose={() => setOpenProModal(false)}
|
219 |
+
/>
|
220 |
</div>
|
221 |
);
|
222 |
}
|
src/components/pro-modal/pro-modal.tsx
ADDED
@@ -0,0 +1,70 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import classNames from "classnames";
|
2 |
+
import { useLocalStorage } from "react-use";
|
3 |
+
import { defaultHTML } from "../../../utils/consts";
|
4 |
+
|
5 |
+
function ProModal({
|
6 |
+
open,
|
7 |
+
html,
|
8 |
+
onClose,
|
9 |
+
}: {
|
10 |
+
open: boolean;
|
11 |
+
html: string;
|
12 |
+
onClose: React.Dispatch<React.SetStateAction<boolean>>;
|
13 |
+
}) {
|
14 |
+
const [, setStorage] = useLocalStorage("html_content");
|
15 |
+
|
16 |
+
const handleProClick = () => {
|
17 |
+
if (html !== defaultHTML) {
|
18 |
+
setStorage(html);
|
19 |
+
}
|
20 |
+
};
|
21 |
+
|
22 |
+
return (
|
23 |
+
<>
|
24 |
+
<div
|
25 |
+
className={classNames(
|
26 |
+
"h-screen w-screen bg-black/20 fixed left-0 top-0 z-40",
|
27 |
+
{
|
28 |
+
"opacity-0 pointer-events-none": !open,
|
29 |
+
}
|
30 |
+
)}
|
31 |
+
onClick={() => onClose(false)}
|
32 |
+
></div>
|
33 |
+
<div
|
34 |
+
className={classNames(
|
35 |
+
"absolute top-0 -translate-y-[calc(100%+16px)] right-0 z-40 w-96 bg-white border border-gray-200 rounded-lg shadow-lg transition-all duration-75 overflow-hidden",
|
36 |
+
{
|
37 |
+
"opacity-0 pointer-events-none": !open,
|
38 |
+
}
|
39 |
+
)}
|
40 |
+
>
|
41 |
+
<header className="flex items-center text-sm px-4 py-2 border-b border-gray-200 gap-2 bg-gray-100 font-semibold text-gray-700">
|
42 |
+
<span className="bg-linear-to-br shadow-green-500/10 dark:shadow-green-500/20 inline-block -skew-x-12 border border-gray-200 from-pink-300 via-green-200 to-yellow-200 text-xs font-bold text-black shadow-lg dark:from-pink-500 dark:via-green-500 dark:to-yellow-500 dark:text-black rounded-lg px-2.5 py-0.5 ">
|
43 |
+
PRO
|
44 |
+
</span>
|
45 |
+
Your free inference quota is exhausted
|
46 |
+
</header>
|
47 |
+
<main className="px-4 pt-3 pb-4">
|
48 |
+
<p className="text-gray-950 text-sm font-semibold flex items-center justify-between">
|
49 |
+
Upgrade to a PRO account to activate Inference Providers and
|
50 |
+
continue using DeepSite.
|
51 |
+
</p>
|
52 |
+
<p className="text-sm text-pretty text-gray-500 mt-2">
|
53 |
+
It also unlocks thousands of Space apps powered by ZeroGPU for 3d,
|
54 |
+
audio, music, video and more!
|
55 |
+
</p>
|
56 |
+
<a
|
57 |
+
href="https://huggingface.co/subscribe/pro"
|
58 |
+
target="_blank"
|
59 |
+
className="mt-4 bg-black text-white cursor-pointer rounded-full py-2 px-3 text-sm font-medium w-full block text-center hover:bg-gray-800 transition duration-200 ease-in-out"
|
60 |
+
onClick={handleProClick}
|
61 |
+
>
|
62 |
+
Subscribe to PRO ($9/month)
|
63 |
+
</a>
|
64 |
+
</main>
|
65 |
+
</div>
|
66 |
+
</>
|
67 |
+
);
|
68 |
+
}
|
69 |
+
|
70 |
+
export default ProModal;
|
src/components/settings/settings.tsx
CHANGED
@@ -30,7 +30,7 @@ function Settings({
|
|
30 |
</button>
|
31 |
<div
|
32 |
className={classNames(
|
33 |
-
"h-screen w-screen bg-black/20 fixed left-0 top-0 z-
|
34 |
{
|
35 |
"opacity-0 pointer-events-none": !open,
|
36 |
}
|
@@ -39,7 +39,7 @@ function Settings({
|
|
39 |
></div>
|
40 |
<div
|
41 |
className={classNames(
|
42 |
-
"absolute top-0 -translate-y-[calc(100%+16px)] right-0 z-
|
43 |
{
|
44 |
"opacity-0 pointer-events-none": !open,
|
45 |
}
|
|
|
30 |
</button>
|
31 |
<div
|
32 |
className={classNames(
|
33 |
+
"h-screen w-screen bg-black/20 fixed left-0 top-0 z-40",
|
34 |
{
|
35 |
"opacity-0 pointer-events-none": !open,
|
36 |
}
|
|
|
39 |
></div>
|
40 |
<div
|
41 |
className={classNames(
|
42 |
+
"absolute top-0 -translate-y-[calc(100%+16px)] right-0 z-40 w-96 bg-white border border-gray-200 rounded-lg shadow-lg transition-all duration-75 overflow-hidden",
|
43 |
{
|
44 |
"opacity-0 pointer-events-none": !open,
|
45 |
}
|