Spaces:
Running
on
CPU Upgrade
Running
on
CPU Upgrade
refacto whole models system
Browse files- package-lock.json +9 -0
- package.json +1 -0
- prisma/schema.prisma +0 -1
- src/lib/components/Button.svelte +4 -1
- src/lib/components/community/Card.svelte +1 -1
- src/lib/components/models/Card.svelte +40 -10
- src/lib/components/models/autocomplete/Autocomplete.svelte +2 -2
- src/lib/components/models/autocomplete/Item.svelte +2 -2
- src/lib/components/models/drawer/Drawer.svelte +3 -2
- src/lib/components/sidebar/Sidebar.svelte +6 -2
- src/lib/stores/use-user.ts +1 -13
- src/lib/type.ts +1 -1
- src/routes/+page.ts +0 -1
- src/routes/api/@me/+server.ts +5 -1
- src/routes/api/models/+server.ts +15 -4
- src/routes/api/models/[id]/+server.ts +96 -2
- src/routes/api/models/submit/+server.ts +0 -1
- src/routes/api/{bulk-create-models β scrap-models}/+server.ts +32 -22
- vite.config.ts +0 -6
package-lock.json
CHANGED
@@ -19,6 +19,7 @@
|
|
19 |
"desm": "^1.3.1",
|
20 |
"express": "^4.18.2",
|
21 |
"js-cookie": "^3.0.5",
|
|
|
22 |
"svelte-infinite-scroll": "^2.0.1"
|
23 |
},
|
24 |
"devDependencies": {
|
@@ -5250,6 +5251,14 @@
|
|
5250 |
"mkdirp": "bin/cmd.js"
|
5251 |
}
|
5252 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
5253 |
"node_modules/mri": {
|
5254 |
"version": "1.2.0",
|
5255 |
"resolved": "https://registry.npmjs.org/mri/-/mri-1.2.0.tgz",
|
|
|
19 |
"desm": "^1.3.1",
|
20 |
"express": "^4.18.2",
|
21 |
"js-cookie": "^3.0.5",
|
22 |
+
"moment": "^2.30.1",
|
23 |
"svelte-infinite-scroll": "^2.0.1"
|
24 |
},
|
25 |
"devDependencies": {
|
|
|
5251 |
"mkdirp": "bin/cmd.js"
|
5252 |
}
|
5253 |
},
|
5254 |
+
"node_modules/moment": {
|
5255 |
+
"version": "2.30.1",
|
5256 |
+
"resolved": "https://registry.npmjs.org/moment/-/moment-2.30.1.tgz",
|
5257 |
+
"integrity": "sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==",
|
5258 |
+
"engines": {
|
5259 |
+
"node": "*"
|
5260 |
+
}
|
5261 |
+
},
|
5262 |
"node_modules/mri": {
|
5263 |
"version": "1.2.0",
|
5264 |
"resolved": "https://registry.npmjs.org/mri/-/mri-1.2.0.tgz",
|
package.json
CHANGED
@@ -52,6 +52,7 @@
|
|
52 |
"desm": "^1.3.1",
|
53 |
"express": "^4.18.2",
|
54 |
"js-cookie": "^3.0.5",
|
|
|
55 |
"svelte-infinite-scroll": "^2.0.1"
|
56 |
}
|
57 |
}
|
|
|
52 |
"desm": "^1.3.1",
|
53 |
"express": "^4.18.2",
|
54 |
"js-cookie": "^3.0.5",
|
55 |
+
"moment": "^2.30.1",
|
56 |
"svelte-infinite-scroll": "^2.0.1"
|
57 |
}
|
58 |
}
|
prisma/schema.prisma
CHANGED
@@ -13,7 +13,6 @@ datasource db {
|
|
13 |
model Model {
|
14 |
id String @id
|
15 |
createdAt DateTime @default(now())
|
16 |
-
title String
|
17 |
image String
|
18 |
likes Int?
|
19 |
downloads Int?
|
|
|
13 |
model Model {
|
14 |
id String @id
|
15 |
createdAt DateTime @default(now())
|
|
|
16 |
image String
|
17 |
likes Int?
|
18 |
downloads Int?
|
src/lib/components/Button.svelte
CHANGED
@@ -3,7 +3,7 @@
|
|
3 |
import Icon from "@iconify/svelte";
|
4 |
import Loading from './Loading.svelte';
|
5 |
|
6 |
-
export let theme: "light" | "dark" | "blue" | "pink" = "light";
|
7 |
export let size: "md" | "lg" = "md";
|
8 |
export let href: string | undefined = undefined;
|
9 |
export let icon: string | undefined = undefined;
|
@@ -73,6 +73,9 @@
|
|
73 |
&.dark {
|
74 |
@apply bg-neutral-900 border-neutral-800 text-neutral-300;
|
75 |
}
|
|
|
|
|
|
|
76 |
&:hover {
|
77 |
@apply brightness-125
|
78 |
}
|
|
|
3 |
import Icon from "@iconify/svelte";
|
4 |
import Loading from './Loading.svelte';
|
5 |
|
6 |
+
export let theme: "light" | "dark" | "blue" | "pink" | "red" = "light";
|
7 |
export let size: "md" | "lg" = "md";
|
8 |
export let href: string | undefined = undefined;
|
9 |
export let icon: string | undefined = undefined;
|
|
|
73 |
&.dark {
|
74 |
@apply bg-neutral-900 border-neutral-800 text-neutral-300;
|
75 |
}
|
76 |
+
&.red {
|
77 |
+
@apply bg-red-500 text-white border-red-500;
|
78 |
+
}
|
79 |
&:hover {
|
80 |
@apply brightness-125
|
81 |
}
|
src/lib/components/community/Card.svelte
CHANGED
@@ -45,7 +45,7 @@
|
|
45 |
on:click={handleClick}
|
46 |
>
|
47 |
<div class="w-full h-full absolute top-0 left-0 -z-[1] rounded-xl overflow-hidden" class:!brightness-50={loading}>
|
48 |
-
<img class="w-full h-full bg-center bg-cover transition-all duration-200 group-hover:scale-110" src="/api/images/{card.image}" alt="{card.prompt}" />
|
49 |
<div class="bg-gradient-to-b from-transparent via-black/50 to-black/70 absolute h-[100px] bottom-0 left-0 w-full"></div>
|
50 |
</div>
|
51 |
<div class="group-hover:opacity-100 opacity-0 translate-y-full group-hover:translate-y-0 transition-all duration-200 flex flex-col gap-4 w-full">
|
|
|
45 |
on:click={handleClick}
|
46 |
>
|
47 |
<div class="w-full h-full absolute top-0 left-0 -z-[1] rounded-xl overflow-hidden" class:!brightness-50={loading}>
|
48 |
+
<img class="w-full h-full bg-center bg-cover transition-all duration-200 group-hover:scale-110 object-cover" src="/api/images/{card.image}" alt="{card.prompt}" />
|
49 |
<div class="bg-gradient-to-b from-transparent via-black/50 to-black/70 absolute h-[100px] bottom-0 left-0 w-full"></div>
|
50 |
</div>
|
51 |
<div class="group-hover:opacity-100 opacity-0 translate-y-full group-hover:translate-y-0 transition-all duration-200 flex flex-col gap-4 w-full">
|
src/lib/components/models/Card.svelte
CHANGED
@@ -1,35 +1,64 @@
|
|
1 |
<script lang="ts">
|
2 |
-
import { modelStore } from "$lib/stores/use-model";
|
3 |
import type { ModelCard } from "$lib/type";
|
4 |
import Icon from "@iconify/svelte";
|
5 |
import { goto } from "$app/navigation";
|
6 |
import { page } from "$app/stores";
|
|
|
|
|
7 |
|
8 |
export let card: ModelCard;
|
9 |
|
|
|
|
|
10 |
const handleClick = async () => {
|
11 |
-
// const request = await fetch(`/api/models/${card?.id?.replace("/", "@")}?full=true`);
|
12 |
-
// const { model } = await request.json();
|
13 |
-
// modelStore.set({
|
14 |
-
// model,
|
15 |
-
// open: true
|
16 |
-
// });
|
17 |
$page.url.searchParams.set('model', card?.id);
|
18 |
goto(`?${$page.url.searchParams.toString()}`);
|
19 |
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
20 |
</script>
|
21 |
|
22 |
<!-- svelte-ignore a11y-no-static-element-interactions -->
|
23 |
<!-- svelte-ignore a11y-click-events-have-key-events -->
|
|
|
24 |
<div
|
25 |
class="w-full cursor-pointer group bg-neutral-900 rounded-xl relative flex items-start justify-between flex-col p-3 border border-neutral-800 transition-all duration-200 brightness-90 hover:brightness-100 z-[1]"
|
26 |
on:click={handleClick}
|
27 |
>
|
28 |
<div class="w-full h-[350px] relative z-[1] mb-3 overflow-hidden">
|
29 |
-
<img src="{card.image}" class="w-full h-full bg-center bg-cover rounded-lg object-cover object-center bg-neutral-800" alt="{card?.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
30 |
</div>
|
31 |
<div class="flex items-center justify-between w-full gap-4 py-1">
|
32 |
-
<p class="text-white font-semibold text-base mb-1 truncate">{card?.
|
33 |
<div class="flex items-center justify-end gap-3">
|
34 |
<div class="text-white text-sm flex items-center justify-end gap-1.5">
|
35 |
<Icon icon="solar:heart-bold" class="w-5 h-5 text-red-500" />
|
@@ -41,4 +70,5 @@
|
|
41 |
</div>
|
42 |
</div>
|
43 |
</div>
|
44 |
-
</div>
|
|
|
|
1 |
<script lang="ts">
|
|
|
2 |
import type { ModelCard } from "$lib/type";
|
3 |
import Icon from "@iconify/svelte";
|
4 |
import { goto } from "$app/navigation";
|
5 |
import { page } from "$app/stores";
|
6 |
+
import Button from "$lib/components/Button.svelte";
|
7 |
+
import { success } from "$lib/utils/toaster";
|
8 |
|
9 |
export let card: ModelCard;
|
10 |
|
11 |
+
let visible = true;
|
12 |
+
|
13 |
const handleClick = async () => {
|
|
|
|
|
|
|
|
|
|
|
|
|
14 |
$page.url.searchParams.set('model', card?.id);
|
15 |
goto(`?${$page.url.searchParams.toString()}`);
|
16 |
};
|
17 |
+
|
18 |
+
const publish = async () => {
|
19 |
+
const request = await fetch(`/api/models/${card.id.replace("/", "@")}`, {
|
20 |
+
method: "POST",
|
21 |
+
});
|
22 |
+
const response = await request.json();
|
23 |
+
if (response.success) {
|
24 |
+
card.isPublic = true;
|
25 |
+
success("Model published successfully!");
|
26 |
+
}
|
27 |
+
};
|
28 |
+
|
29 |
+
const remove = async () => {
|
30 |
+
const request = await fetch(`/api/models/${card.id.replace("/", "@")}`, {
|
31 |
+
method: "DELETE",
|
32 |
+
});
|
33 |
+
const response = await request.json();
|
34 |
+
if (response.success) {
|
35 |
+
visible = false;
|
36 |
+
success("Model deleted successfully!");
|
37 |
+
}
|
38 |
+
};
|
39 |
</script>
|
40 |
|
41 |
<!-- svelte-ignore a11y-no-static-element-interactions -->
|
42 |
<!-- svelte-ignore a11y-click-events-have-key-events -->
|
43 |
+
{#if visible}
|
44 |
<div
|
45 |
class="w-full cursor-pointer group bg-neutral-900 rounded-xl relative flex items-start justify-between flex-col p-3 border border-neutral-800 transition-all duration-200 brightness-90 hover:brightness-100 z-[1]"
|
46 |
on:click={handleClick}
|
47 |
>
|
48 |
<div class="w-full h-[350px] relative z-[1] mb-3 overflow-hidden">
|
49 |
+
<img src="{card.image}" class="w-full h-full bg-center bg-cover rounded-lg object-cover object-center bg-neutral-800" alt="{card?.id}" />
|
50 |
+
{#if !card.isPublic}
|
51 |
+
<div
|
52 |
+
class="absolute flex items-center justify-between bottom-0 left-0 w-full p-5 bg-neutral-900/30"
|
53 |
+
on:click={e => e.stopPropagation()}
|
54 |
+
>
|
55 |
+
<Button theme="red" onClick={remove}>Delete</Button>
|
56 |
+
<Button theme="blue" icon="icon-park-solid:check-one" onClick={publish}>Publish</Button>
|
57 |
+
</div>
|
58 |
+
{/if}
|
59 |
</div>
|
60 |
<div class="flex items-center justify-between w-full gap-4 py-1">
|
61 |
+
<p class="text-white font-semibold text-base mb-1 truncate">{card?.id}</p>
|
62 |
<div class="flex items-center justify-end gap-3">
|
63 |
<div class="text-white text-sm flex items-center justify-end gap-1.5">
|
64 |
<Icon icon="solar:heart-bold" class="w-5 h-5 text-red-500" />
|
|
|
70 |
</div>
|
71 |
</div>
|
72 |
</div>
|
73 |
+
</div>
|
74 |
+
{/if}
|
src/lib/components/models/autocomplete/Autocomplete.svelte
CHANGED
@@ -51,8 +51,8 @@
|
|
51 |
{#if value}
|
52 |
<div class="flex items-center justify-between gap-4">
|
53 |
<div class="flex items-center justify-start gap-3">
|
54 |
-
<img src={value.image} alt={value.
|
55 |
-
<p class="text-neutral-200 text-base font-medium">{value.
|
56 |
</div>
|
57 |
<button on:click={() => onChange(null)}>
|
58 |
<Icon icon="maki:cross" class="w-4 h-4 text-neutral-500 transition-all duration-200 cursor-pointer" />
|
|
|
51 |
{#if value}
|
52 |
<div class="flex items-center justify-between gap-4">
|
53 |
<div class="flex items-center justify-start gap-3">
|
54 |
+
<img src={value.image} alt={value.id} class="w-6 h-6 rounded-lg object-cover" />
|
55 |
+
<p class="text-neutral-200 text-base font-medium">{value.id}</p>
|
56 |
</div>
|
57 |
<button on:click={() => onChange(null)}>
|
58 |
<Icon icon="maki:cross" class="w-4 h-4 text-neutral-500 transition-all duration-200 cursor-pointer" />
|
src/lib/components/models/autocomplete/Item.svelte
CHANGED
@@ -10,9 +10,9 @@
|
|
10 |
class="flex items-center justify-start gap-4 px-2 py-2.5 hover:bg-neutral-800/60 transition-all duration-200 rounded-lg cursor-pointer w-full text-left"
|
11 |
on:click={onClick}
|
12 |
>
|
13 |
-
<img src={model.image} alt={model.
|
14 |
<div>
|
15 |
-
<p class="text-neutral-200 text-base font-medium">{model.
|
16 |
<p class="text-neutral-400 text-sm">{model.id}</p>
|
17 |
</div>
|
18 |
</button>
|
|
|
10 |
class="flex items-center justify-start gap-4 px-2 py-2.5 hover:bg-neutral-800/60 transition-all duration-200 rounded-lg cursor-pointer w-full text-left"
|
11 |
on:click={onClick}
|
12 |
>
|
13 |
+
<img src={model.image} alt={model.id} class="w-14 h-14 rounded-lg object-cover" />
|
14 |
<div>
|
15 |
+
<p class="text-neutral-200 text-base font-medium">{model.id}</p>
|
16 |
<p class="text-neutral-400 text-sm">{model.id}</p>
|
17 |
</div>
|
18 |
</button>
|
src/lib/components/models/drawer/Drawer.svelte
CHANGED
@@ -56,7 +56,7 @@
|
|
56 |
<img src={model?.image} class="lg:w-16 lg:h-16 w-12 h-12 rounded-xl bg-neutral-800 object-cover" alt={model?.id} />
|
57 |
<div>
|
58 |
<p class="text-white font-semibold text-lg lg:text-2xl mb-1 truncate">
|
59 |
-
{model?.
|
60 |
</p>
|
61 |
<a href="https://huggingface.co/{model?.id}" target="_blank" class="text-neutral-400 underline hover:text-neutral-300 flex items-center justify-start gap-1">
|
62 |
<Icon icon="iconamoon:link-external-fill" class="w-4 h-4" />
|
@@ -75,7 +75,8 @@
|
|
75 |
{model?.likes ?? 0}
|
76 |
</div>
|
77 |
<a
|
78 |
-
|
|
|
79 |
class="bg-blue-500 bg-opacity-20 border border-blue-500 hover:bg-opacity-60 transition-all duration-200 md:px-4 md:py-2 px-3 py-1.5 rounded-full text-neutral-100 flex items-center justify-center gap-1 md:gap-2 font-medium text-sm md:text-base"
|
80 |
>
|
81 |
<Icon icon="solar:download-square-bold" class="lg:w-5 lg:h-5 w-4 h-4 text-blue-500" />
|
|
|
56 |
<img src={model?.image} class="lg:w-16 lg:h-16 w-12 h-12 rounded-xl bg-neutral-800 object-cover" alt={model?.id} />
|
57 |
<div>
|
58 |
<p class="text-white font-semibold text-lg lg:text-2xl mb-1 truncate">
|
59 |
+
{model?.id}
|
60 |
</p>
|
61 |
<a href="https://huggingface.co/{model?.id}" target="_blank" class="text-neutral-400 underline hover:text-neutral-300 flex items-center justify-start gap-1">
|
62 |
<Icon icon="iconamoon:link-external-fill" class="w-4 h-4" />
|
|
|
75 |
{model?.likes ?? 0}
|
76 |
</div>
|
77 |
<a
|
78 |
+
href="https://huggingface.co/{model?.id}/tree/main"
|
79 |
+
target="_blank"
|
80 |
class="bg-blue-500 bg-opacity-20 border border-blue-500 hover:bg-opacity-60 transition-all duration-200 md:px-4 md:py-2 px-3 py-1.5 rounded-full text-neutral-100 flex items-center justify-center gap-1 md:gap-2 font-medium text-sm md:text-base"
|
81 |
>
|
82 |
<Icon icon="solar:download-square-bold" class="lg:w-5 lg:h-5 w-4 h-4 text-blue-500" />
|
src/lib/components/sidebar/Sidebar.svelte
CHANGED
@@ -26,7 +26,6 @@
|
|
26 |
window.location.href = "/";
|
27 |
}
|
28 |
|
29 |
-
// sveltekit close sidebar on route change
|
30 |
if (browser) {
|
31 |
page.subscribe((value) => {
|
32 |
if (isOpen) handleClick();
|
@@ -69,7 +68,12 @@
|
|
69 |
<div class="flex items-center justify-start gap-4">
|
70 |
<img src={user.picture} alt="User avatar" class="w-10 h-10 rounded-full border-2 border-white inline-block" />
|
71 |
<div class="w-full text-left">
|
72 |
-
<p class="text-lg font-semibold">
|
|
|
|
|
|
|
|
|
|
|
73 |
<p class="text-sm leading-none text-neutral-400">{user.preferred_username}</p>
|
74 |
</div>
|
75 |
</div>
|
|
|
26 |
window.location.href = "/";
|
27 |
}
|
28 |
|
|
|
29 |
if (browser) {
|
30 |
page.subscribe((value) => {
|
31 |
if (isOpen) handleClick();
|
|
|
68 |
<div class="flex items-center justify-start gap-4">
|
69 |
<img src={user.picture} alt="User avatar" class="w-10 h-10 rounded-full border-2 border-white inline-block" />
|
70 |
<div class="w-full text-left">
|
71 |
+
<p class="text-lg font-semibold">
|
72 |
+
{user.name}
|
73 |
+
{#if user?.is_admin}
|
74 |
+
<span class="text-yellow-400 bg-yellow-500 bg-opacity-20 rounded-lg px-2 py-1 text-xs font-semibold ml-1">HF Staff</span>
|
75 |
+
{/if}
|
76 |
+
</p>
|
77 |
<p class="text-sm leading-none text-neutral-400">{user.preferred_username}</p>
|
78 |
</div>
|
79 |
</div>
|
src/lib/stores/use-user.ts
CHANGED
@@ -6,16 +6,4 @@ export const userStore = writable<any>(null);
|
|
6 |
|
7 |
export const openWindowLogin = async () => {
|
8 |
window.open("/api/auth/login", "_blank");
|
9 |
-
};
|
10 |
-
|
11 |
-
// export const loginFromCode = async (code: string) => {
|
12 |
-
// const request = await fetch(`/api/auth`, {
|
13 |
-
// method: "POST",
|
14 |
-
// body: JSON.stringify({ code }),
|
15 |
-
// });
|
16 |
-
// const { ok, token } = await request.json();
|
17 |
-
// if (ok) {
|
18 |
-
// cookies.set("hf_access_token", token, { expires: 1, domain: process.env.SPACE_HOST });
|
19 |
-
// window.location.reload();
|
20 |
-
// }
|
21 |
-
// };
|
|
|
6 |
|
7 |
export const openWindowLogin = async () => {
|
8 |
window.open("/api/auth/login", "_blank");
|
9 |
+
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/lib/type.ts
CHANGED
@@ -16,12 +16,12 @@ export interface CommunityCard {
|
|
16 |
}
|
17 |
|
18 |
export interface ModelCard {
|
19 |
-
title: string,
|
20 |
id: string,
|
21 |
likes: number,
|
22 |
downloads: number,
|
23 |
image: string,
|
24 |
instance_prompt?: string,
|
|
|
25 |
gallery?: CommunityCard[],
|
26 |
comments?: CommentType[],
|
27 |
infos?: {
|
|
|
16 |
}
|
17 |
|
18 |
export interface ModelCard {
|
|
|
19 |
id: string,
|
20 |
likes: number,
|
21 |
downloads: number,
|
22 |
image: string,
|
23 |
instance_prompt?: string,
|
24 |
+
isPublic: boolean,
|
25 |
gallery?: CommunityCard[],
|
26 |
comments?: CommentType[],
|
27 |
infos?: {
|
src/routes/+page.ts
CHANGED
@@ -3,7 +3,6 @@ import { modelStore } from "$lib/stores/use-model";
|
|
3 |
export async function load({ fetch, url }) {
|
4 |
const model_param = url.searchParams.get("model")
|
5 |
|
6 |
-
|
7 |
if (model_param) {
|
8 |
const model_request = await fetch(`/api/models/${model_param?.replace("/", "@")}?full=true`, {
|
9 |
method: "GET",
|
|
|
3 |
export async function load({ fetch, url }) {
|
4 |
const model_param = url.searchParams.get("model")
|
5 |
|
|
|
6 |
if (model_param) {
|
7 |
const model_request = await fetch(`/api/models/${model_param?.replace("/", "@")}?full=true`, {
|
8 |
method: "GET",
|
src/routes/api/@me/+server.ts
CHANGED
@@ -1,5 +1,6 @@
|
|
1 |
import { json, type RequestEvent } from '@sveltejs/kit';
|
2 |
import prisma from '$lib/prisma';
|
|
|
3 |
|
4 |
/** @type {import('./$types').RequestHandler} */
|
5 |
|
@@ -60,6 +61,9 @@ export async function GET(request : RequestEvent) {
|
|
60 |
}
|
61 |
|
62 |
return json({
|
63 |
-
user
|
|
|
|
|
|
|
64 |
})
|
65 |
}
|
|
|
1 |
import { json, type RequestEvent } from '@sveltejs/kit';
|
2 |
import prisma from '$lib/prisma';
|
3 |
+
import { env } from '$env/dynamic/private';
|
4 |
|
5 |
/** @type {import('./$types').RequestHandler} */
|
6 |
|
|
|
61 |
}
|
62 |
|
63 |
return json({
|
64 |
+
user: {
|
65 |
+
...user,
|
66 |
+
is_admin: env.SECRET_HF_ADMIN.includes(user.sub)
|
67 |
+
}
|
68 |
})
|
69 |
}
|
src/routes/api/models/+server.ts
CHANGED
@@ -1,9 +1,22 @@
|
|
1 |
import { json, type RequestEvent } from '@sveltejs/kit';
|
2 |
import prisma from '$lib/prisma';
|
|
|
|
|
|
|
3 |
|
4 |
/** @type {import('./$types').RequestHandler} */
|
5 |
|
6 |
export async function GET(request : RequestEvent) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
7 |
const page = parseInt(request.url.searchParams.get('page') || '0')
|
8 |
const filter = request.url.searchParams.get('filter') || 'hotest'
|
9 |
const search = request.url.searchParams.get('search') || ''
|
@@ -11,9 +24,8 @@ export async function GET(request : RequestEvent) {
|
|
11 |
|
12 |
const cards = await prisma.model.findMany({
|
13 |
where: {
|
14 |
-
isPublic: true,
|
15 |
OR: [
|
16 |
-
{ title: { contains: search } },
|
17 |
{ id: { contains: search } },
|
18 |
]
|
19 |
},
|
@@ -26,9 +38,8 @@ export async function GET(request : RequestEvent) {
|
|
26 |
|
27 |
const total_reposId = await prisma.model.count({
|
28 |
where: {
|
29 |
-
isPublic: true,
|
30 |
OR: [
|
31 |
-
{ title: { contains: search } },
|
32 |
{ id: { contains: search } },
|
33 |
]
|
34 |
},
|
|
|
1 |
import { json, type RequestEvent } from '@sveltejs/kit';
|
2 |
import prisma from '$lib/prisma';
|
3 |
+
import { env } from '$env/dynamic/private';
|
4 |
+
|
5 |
+
import { tokenIsAvailable } from '$lib/utils';
|
6 |
|
7 |
/** @type {import('./$types').RequestHandler} */
|
8 |
|
9 |
export async function GET(request : RequestEvent) {
|
10 |
+
const token = request.cookies.get('hf_access_token')
|
11 |
+
let IS_ADMIN = !!token
|
12 |
+
|
13 |
+
if (token) {
|
14 |
+
const user = await tokenIsAvailable(token)
|
15 |
+
if (user) {
|
16 |
+
IS_ADMIN = env.SECRET_HF_ADMIN.includes(user.sub)
|
17 |
+
}
|
18 |
+
}
|
19 |
+
|
20 |
const page = parseInt(request.url.searchParams.get('page') || '0')
|
21 |
const filter = request.url.searchParams.get('filter') || 'hotest'
|
22 |
const search = request.url.searchParams.get('search') || ''
|
|
|
24 |
|
25 |
const cards = await prisma.model.findMany({
|
26 |
where: {
|
27 |
+
...(IS_ADMIN ? {} : { isPublic: true }),
|
28 |
OR: [
|
|
|
29 |
{ id: { contains: search } },
|
30 |
]
|
31 |
},
|
|
|
38 |
|
39 |
const total_reposId = await prisma.model.count({
|
40 |
where: {
|
41 |
+
...(IS_ADMIN ? {} : { isPublic: true }),
|
42 |
OR: [
|
|
|
43 |
{ id: { contains: search } },
|
44 |
]
|
45 |
},
|
src/routes/api/models/[id]/+server.ts
CHANGED
@@ -1,6 +1,7 @@
|
|
1 |
import { json, type RequestEvent } from '@sveltejs/kit';
|
2 |
import { env } from '$env/dynamic/private'
|
3 |
import prisma from '$lib/prisma';
|
|
|
4 |
|
5 |
/** @type {import('./$types').RequestHandler} */
|
6 |
|
@@ -18,7 +19,6 @@ export async function GET({ url, params } : RequestEvent) {
|
|
18 |
likes: true,
|
19 |
downloads: true,
|
20 |
image: true,
|
21 |
-
title: true,
|
22 |
instance_prompt: true,
|
23 |
gallery: {
|
24 |
select: {
|
@@ -54,7 +54,6 @@ export async function GET({ url, params } : RequestEvent) {
|
|
54 |
} : {
|
55 |
instance_prompt: true,
|
56 |
image: true,
|
57 |
-
title: true,
|
58 |
id: true,
|
59 |
}
|
60 |
})
|
@@ -90,3 +89,98 @@ export async function GET({ url, params } : RequestEvent) {
|
|
90 |
}
|
91 |
})
|
92 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
import { json, type RequestEvent } from '@sveltejs/kit';
|
2 |
import { env } from '$env/dynamic/private'
|
3 |
import prisma from '$lib/prisma';
|
4 |
+
import { tokenIsAvailable } from '$lib/utils';
|
5 |
|
6 |
/** @type {import('./$types').RequestHandler} */
|
7 |
|
|
|
19 |
likes: true,
|
20 |
downloads: true,
|
21 |
image: true,
|
|
|
22 |
instance_prompt: true,
|
23 |
gallery: {
|
24 |
select: {
|
|
|
54 |
} : {
|
55 |
instance_prompt: true,
|
56 |
image: true,
|
|
|
57 |
id: true,
|
58 |
}
|
59 |
})
|
|
|
89 |
}
|
90 |
})
|
91 |
}
|
92 |
+
|
93 |
+
export async function POST({ params, cookies } : RequestEvent) {
|
94 |
+
const token = cookies.get('hf_access_token')
|
95 |
+
if (!token) {
|
96 |
+
return json({
|
97 |
+
error: {
|
98 |
+
token: "Token is required"
|
99 |
+
}
|
100 |
+
}, { status: 401 })
|
101 |
+
}
|
102 |
+
|
103 |
+
const user = await tokenIsAvailable(token)
|
104 |
+
if (!user || !env.SECRET_HF_ADMIN.includes(user.sub)) {
|
105 |
+
return json({
|
106 |
+
error: {
|
107 |
+
token: "Wrong castle fam :^)"
|
108 |
+
}
|
109 |
+
}, { status: 401 })
|
110 |
+
}
|
111 |
+
|
112 |
+
const id = params.id?.replace("@", "/")
|
113 |
+
|
114 |
+
const model = await prisma.model.findFirst({
|
115 |
+
where: {
|
116 |
+
id,
|
117 |
+
}
|
118 |
+
})
|
119 |
+
|
120 |
+
if (!model) {
|
121 |
+
return json({
|
122 |
+
error: {
|
123 |
+
token: "Model not found"
|
124 |
+
}
|
125 |
+
}, { status: 404 })
|
126 |
+
}
|
127 |
+
|
128 |
+
await prisma.model.update({
|
129 |
+
where: {
|
130 |
+
id,
|
131 |
+
},
|
132 |
+
data: {
|
133 |
+
isPublic: true,
|
134 |
+
}
|
135 |
+
})
|
136 |
+
|
137 |
+
return json({
|
138 |
+
success: true
|
139 |
+
})
|
140 |
+
}
|
141 |
+
|
142 |
+
export async function DELETE({ params, cookies } : RequestEvent) {
|
143 |
+
const token = cookies.get('hf_access_token')
|
144 |
+
if (!token) {
|
145 |
+
return json({
|
146 |
+
error: {
|
147 |
+
token: "Token is required"
|
148 |
+
}
|
149 |
+
}, { status: 401 })
|
150 |
+
}
|
151 |
+
|
152 |
+
const user = await tokenIsAvailable(token)
|
153 |
+
if (!user || !env.SECRET_HF_ADMIN.includes(user.sub)) {
|
154 |
+
return json({
|
155 |
+
error: {
|
156 |
+
token: "Wrong castle fam :^)"
|
157 |
+
}
|
158 |
+
}, { status: 401 })
|
159 |
+
}
|
160 |
+
|
161 |
+
const id = params.id?.replace("@", "/")
|
162 |
+
|
163 |
+
const model = await prisma.model.findFirst({
|
164 |
+
where: {
|
165 |
+
id,
|
166 |
+
}
|
167 |
+
})
|
168 |
+
|
169 |
+
if (!model) {
|
170 |
+
return json({
|
171 |
+
error: {
|
172 |
+
token: "Model not found"
|
173 |
+
}
|
174 |
+
}, { status: 404 })
|
175 |
+
}
|
176 |
+
|
177 |
+
await prisma.model.delete({
|
178 |
+
where: {
|
179 |
+
id,
|
180 |
+
}
|
181 |
+
})
|
182 |
+
|
183 |
+
return json({
|
184 |
+
success: true
|
185 |
+
})
|
186 |
+
}
|
src/routes/api/models/submit/+server.ts
CHANGED
@@ -56,7 +56,6 @@ export async function POST({ request, fetch, cookies }) {
|
|
56 |
data: {
|
57 |
id: model.id,
|
58 |
image: model.image,
|
59 |
-
title: model.title,
|
60 |
likes: data.likes,
|
61 |
downloads: data.downloads,
|
62 |
isPublic: false,
|
|
|
56 |
data: {
|
57 |
id: model.id,
|
58 |
image: model.image,
|
|
|
59 |
likes: data.likes,
|
60 |
downloads: data.downloads,
|
61 |
isPublic: false,
|
src/routes/api/{bulk-create-models β scrap-models}/+server.ts
RENAMED
@@ -1,6 +1,7 @@
|
|
1 |
/** @type {import('./$types').RequestHandler} */
|
2 |
|
3 |
import { json } from '@sveltejs/kit';
|
|
|
4 |
import prisma from '$lib/prisma';
|
5 |
import { env } from '$env/dynamic/private'
|
6 |
|
@@ -13,39 +14,48 @@ export async function POST({ request }) {
|
|
13 |
}, { status: 401 });
|
14 |
}
|
15 |
|
16 |
-
const
|
|
|
17 |
|
18 |
-
|
19 |
-
|
20 |
-
|
21 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
22 |
}
|
23 |
-
|
24 |
-
|
25 |
-
|
26 |
-
|
27 |
-
|
28 |
-
|
29 |
-
likes: data.likes,
|
30 |
-
instance_prompt: data?.cardData?.instance_prompt ?? null,
|
31 |
-
downloads: data.downloads,
|
32 |
}
|
33 |
-
return mergedData
|
34 |
-
}
|
35 |
-
))
|
36 |
|
37 |
-
for (const model of cards) {
|
38 |
await prisma.model.create({
|
39 |
data: {
|
40 |
id: model.id,
|
41 |
image: model.image,
|
42 |
-
title: model.title,
|
43 |
likes: model.likes,
|
44 |
-
instance_prompt: model.instance_prompt,
|
45 |
downloads: model.downloads,
|
46 |
-
isPublic:
|
47 |
}
|
48 |
-
})
|
|
|
|
|
49 |
}
|
50 |
|
51 |
const total_items = await prisma.model.count()
|
|
|
1 |
/** @type {import('./$types').RequestHandler} */
|
2 |
|
3 |
import { json } from '@sveltejs/kit';
|
4 |
+
// import moment from 'moment';
|
5 |
import prisma from '$lib/prisma';
|
6 |
import { env } from '$env/dynamic/private'
|
7 |
|
|
|
14 |
}, { status: 401 });
|
15 |
}
|
16 |
|
17 |
+
const response = await fetch(`https://huggingface.co/api/models?limit=5000&filter=lora%2Cdiffusers&sort=createdAt&full=true&config=true`)
|
18 |
+
const responseData = await response.json();
|
19 |
|
20 |
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
21 |
+
let index = 0;
|
22 |
+
for (const model of responseData) {
|
23 |
+
if (index % 50 === 0) {
|
24 |
+
await new Promise(resolve => setTimeout(resolve, 4000));
|
25 |
+
}
|
26 |
+
|
27 |
+
const hasReadme = model?.siblings?.find((sibling: Record<string, string>) => sibling?.rfilename === "README.md")
|
28 |
+
if (hasReadme) {
|
29 |
+
const readmeRes = await fetch(`https://huggingface.co/${model.id}/raw/main/README.md`)
|
30 |
+
const readme = await readmeRes.text().catch(() => null)
|
31 |
+
if (!readme) {
|
32 |
+
continue
|
33 |
+
}
|
34 |
+
const imageRegex = /!\[.*\]\((.*)\)/
|
35 |
+
const image = readme.match(imageRegex)?.[1]
|
36 |
+
|
37 |
+
if (!image) {
|
38 |
+
continue
|
39 |
}
|
40 |
+
if (image.startsWith("http")) model.image = image
|
41 |
+
else if (image.includes(model.id)) {
|
42 |
+
const path = image.split("/")
|
43 |
+
model.image = `https://huggingface.co/${model.id}/raw/main/${path[path.length - 1]}`
|
44 |
+
}
|
45 |
+
else model.image = `https://huggingface.co/${model.id}/raw/main/${image.replace("./", "")}`
|
|
|
|
|
|
|
46 |
}
|
|
|
|
|
|
|
47 |
|
|
|
48 |
await prisma.model.create({
|
49 |
data: {
|
50 |
id: model.id,
|
51 |
image: model.image,
|
|
|
52 |
likes: model.likes,
|
|
|
53 |
downloads: model.downloads,
|
54 |
+
isPublic: false,
|
55 |
}
|
56 |
+
}).catch(() => {})
|
57 |
+
|
58 |
+
index++
|
59 |
}
|
60 |
|
61 |
const total_items = await prisma.model.count()
|
vite.config.ts
CHANGED
@@ -7,10 +7,4 @@ export default defineConfig({
|
|
7 |
enhancedImages(),
|
8 |
sveltekit(),
|
9 |
],
|
10 |
-
// server: {
|
11 |
-
// fs: {
|
12 |
-
// strict: false,
|
13 |
-
// allow: [".."],
|
14 |
-
// },
|
15 |
-
// }
|
16 |
});
|
|
|
7 |
enhancedImages(),
|
8 |
sveltekit(),
|
9 |
],
|
|
|
|
|
|
|
|
|
|
|
|
|
10 |
});
|