···1515};
16161717export async function GET() {
1818- const uploadIds = await fetch(`${process.env.NEXT_PUBLIC_API}/ai/sitemap`, fetchOptions).then((res) => res.json()) as string[];
1918 const guildIds = await fetch(`${process.env.NEXT_PUBLIC_API}/guilds`, fetchOptions).then((res) => res.json()) as string[];
20192120 const sitemap = [
···75747675 for (const page of docsMetadata.pages) sitemap.push({ url: getCanonicalUrl("docs", page.file.split(".")[0]), priority: 0.6 });
7776 for (const guildId of guildIds) sitemap.push({ url: getCanonicalUrl("leaderboard", guildId), priority: 0.5 });
7878- for (const uploadId of uploadIds) sitemap.push({ url: getCanonicalUrl("ai-gallery", uploadId), priority: 0.4 });
79778078 return new Response(`
8179 <urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
+3-3
app/(home)/faq.component.tsx
···3737 },
3838 {
3939 startContent: <HiCash />,
4040- title: "Is the /image Ai or Text to Speech free to use?",
4040+ title: "Is Text to Speech free to use?",
4141 content: (
4242 <div>
4343- Yes, the image Ai and Text to Speech are free to use. However, you might have to <LinkTag href="/vote">vote for Wamellow on top.gg</LinkTag> if you start using it a lot.
4343+ Yes, Text to Speech is free to use. However, you might have to <LinkTag href="/vote">vote for Wamellow on top.gg</LinkTag> if you start using it a lot.
4444 </div>
4545 )
4646 },
···120120 title: "Which social platforms does Wamellow Notifications support?",
121121 content: (
122122 <div itemProp="text">
123123- Wamellow currently support YouTube videos, shorts and livestreams; Twitch live stream; and Bluesky (bsky.app) posts, reposts and quote-replies.
123123+ Wamellow currently support YouTube videos, shorts and livestreams; Twitch live stream; Bluesky (bsky.app) posts, reposts and quote-replies; and Reddit posts.
124124 </div>
125125 )
126126 }
+3-3
app/(home)/page.tsx
···96969797 <span className="text-lg font-medium max-w-[38rem] mb-4">
9898 Engage in leaderboards, starboards, and a welcoming atmosphere.
9999- Dive into /anime's, free /image Ai, and the power of Text-to-Speech.
9999+ Dive into /anime's, free chat ai, and the power of Text-to-Speech.
100100 Stay updated with dailyposts and receive social notifications!
101101 </span>
102102···374374 <div>
375375 <h2 className={styles.h2}>Watchin{"'"} Anime ❤️</h2>
376376377377- <Box className="flex flex-col md:flex-row-reverse gap-10 items-center">
377377+ <Box className="flex flex-col md:flex-row gap-10 items-center">
378378 <div className="md:w-1/2">
379379 <Badge
380380 className="mb-2"
···431431 <div>
432432 <h2 className={styles.h2}>Fun leveling and leaderboards 🦄</h2>
433433434434- <Box className="flex flex-col md:flex-row gap-10 items-center">
434434+ <Box className="flex flex-col md:flex-row-reverse gap-10 items-center">
435435 <div className="md:w-1/2">
436436 <Badge
437437 className="mb-2"
-1
app/[pathname]/page.tsx
···1818 case "logout": return redirect("/login?logout=true");
1919 case "docs":
2020 case "guides": return redirect("/docs/index");
2121- case "ai": return redirect("/ai-gallery");
2221 case "tts": return redirect("https://youtube.com/watch?v=NS5fZ1ltovE");
2322 case "disable-commands": return redirect("https://youtube.com/watch?v=ehc0_whydu8");
2423 case "youtube": return redirect("https://www.youtube.com/channel/UClWBeVcz5LUmcCN1gHG_GCg");
···11-"use client";
22-33-import { Accordion, AccordionItem } from "@nextui-org/react";
44-import Link from "next/link";
55-import { useCookies } from "next-client-cookies";
66-import { HiHand, HiUserGroup } from "react-icons/hi";
77-88-import Ad from "@/components/ad";
99-import ImageReduceMotion from "@/components/image-reduce-motion";
1010-import { Share } from "@/components/share";
1111-import { formatDate } from "@/components/time";
1212-import { Badge } from "@/components/ui/badge";
1313-import type { AnalyticsError, AnalyticsResponse } from "@/lib/analytics";
1414-import type { ApiError, ApiV1GuildsGetResponse, ApiV1UploadGetResponse } from "@/typings";
1515-import { getCanonicalUrl } from "@/utils/urls";
1616-1717-export default function Side({
1818- upload,
1919- guild,
2020- analytics
2121-}: {
2222- upload: ApiV1UploadGetResponse | ApiError;
2323- guild: ApiV1GuildsGetResponse | ApiError | undefined;
2424- analytics: { results: AnalyticsResponse[]; } | AnalyticsError | undefined;
2525-}) {
2626- const cookies = useCookies();
2727-2828- return (
2929- <div className="flex flex-col gap-3">
3030- {"prompt" in upload &&
3131- <Share
3232- title="Share image"
3333- url={getCanonicalUrl("ai-gallery", upload.id)}
3434- text={`${upload.author.username} created an #ai image with the #wamellow bot for #discord using ${upload.model}!`}
3535- />
3636- }
3737-3838- <Ad
3939- title="/image AI for free"
4040- description="Create your own amazing AI /image's with Wamellow for free in your Discord Server using the best SDXL models and 40+ more!"
4141- />
4242-4343- <Accordion
4444- variant="shadow"
4545- className="bg-wamellow"
4646- selectionMode="multiple"
4747- defaultExpandedKeys={["1"]}
4848- disableAnimation={cookies.get("reduceMotions") === "true"}
4949- >
5050- <AccordionItem
5151- key="1"
5252- aria-label="about"
5353- title="About"
5454- classNames={{ content: "mb-2 space-y-4" }}
5555- >
5656-5757- <div className="flex items-center justify-between">
5858- <span>Created</span>
5959- <Badge>
6060- {"createdAt" in upload ?
6161- formatDate(upload.createdAt as string, "en-US")
6262- :
6363- "unknown"
6464- }
6565- </Badge>
6666- </div>
6767-6868- {analytics && "results" in analytics &&
6969- <div className="flex items-center justify-between">
7070- Views
7171- <Badge>
7272- {Array.isArray(analytics.results) && analytics.results.length ?
7373- (analytics.results[0].pageviews)
7474- :
7575- "unknown"
7676- }
7777- {" "}
7878- views
7979- </Badge>
8080- </div>
8181- }
8282-8383- {"author" in upload &&
8484- <div className="flex items-center justify-between">
8585- Author
8686- <Badge className="flex">
8787- <ImageReduceMotion
8888- className="rounded-full relative right-1"
8989- alt="uploader's avatar"
9090- url={"https://cdn.discordapp.com/avatars/" + upload.authorId + "/" + upload.author.avatar}
9191- size={16}
9292- />
9393-9494- {upload.author.username}
9595-9696- {upload.author.bot &&
9797- <Badge
9898- className="relative left-1"
9999- color="secondary"
100100- variant="flat"
101101- size="xs"
102102- >
103103- BOT
104104- </Badge>
105105- }
106106- </Badge>
107107- </div>
108108- }
109109-110110- <div className="flex items-center justify-between">
111111- Rating
112112- <Badge
113113- className="font-bold select-none"
114114- variant={"nsfw" in upload && upload.nsfw ? "destructive" : "default"}
115115- >
116116- {"nsfw" in upload && upload.nsfw
117117- ? <HiHand />
118118- : <HiUserGroup />
119119- }
120120- {"nsfw" in upload && upload.nsfw ? "Mature" : "Everyone"}
121121- </Badge>
122122- </div>
123123-124124- </AccordionItem>
125125- </Accordion>
126126-127127- <Accordion
128128- variant="shadow"
129129- className="bg-wamellow"
130130- selectionMode="multiple"
131131- disableAnimation={cookies.get("reduceMotions") === "true"}
132132- >
133133- <AccordionItem
134134- key="1"
135135- aria-label="command"
136136- title="Command"
137137- classNames={{ content: "mb-2 space-y-4" }}
138138- subtitle="Copy it and run it in Discord"
139139- >
140140- {"prompt" in upload &&
141141- <span className="select-all">
142142- /image query: {upload?.prompt} {upload?.negativePrompt && `negative-query: ${upload?.negativePrompt}`} model: {upload?.model}
143143- </span>
144144- }
145145- </AccordionItem>
146146- </Accordion>
147147-148148- {guild && "id" in guild &&
149149- <Link
150150- href={getCanonicalUrl("leaderboard", guild.id, "?utm_source=wamellow.com&utm_medium=ai-gallery")}
151151- target="_blank"
152152- className="flex gap-3 items-center border-2 border-wamellow p-3 rounded-lg shadow-md"
153153- >
154154- <ImageReduceMotion
155155- className="rounded-full h-12 w-12"
156156- alt="Server icon"
157157- url={`https://cdn.discordapp.com/icons/${guild.id}/${guild.icon}`}
158158- size={56}
159159- />
160160-161161- <div>
162162- <div className="text-lg text-neutral-200 font-semibold truncate">{guild.name}</div>
163163- <div className="text-sm font-medium">View leaderboard</div>
164164- </div>
165165- </Link>
166166- }
167167-168168- <div className="hidden xl:block">
169169- The image has been generated by artificial intelligence (AI) and not by a human creator. Wamellow and its developers disclaim any responsibility for the content of the images and reserve all rights to the media.
170170- </div>
171171-172172- </div>
173173- );
174174-175175-}
-36
app/ai-gallery/api.ts
···11-import { defaultFetchOptions } from "@/lib/api";
22-import type {
33- ApiError,
44- ApiV1UploadGetResponse,
55- ApiV1UploadsGetResponse
66-} from "@/typings";
77-88-export async function getUploads(options?: Partial<{
99- model: string;
1010- nsfw: boolean;
1111- page: number;
1212- query: string;
1313-}>): Promise<ApiV1UploadsGetResponse | ApiError> {
1414-1515- const params = new URLSearchParams();
1616- if (options?.model) params.append("model", options.model);
1717- if (options?.nsfw) params.append("nsfw", options.nsfw.toString());
1818- if (options?.page) params.append("page", (options.page - 1).toString());
1919- if (options?.query) params.append("query", options.query);
2020-2121- const res = await fetch(
2222- `${process.env.NEXT_PUBLIC_API}/ai?${params.toString()}`,
2323- defaultFetchOptions
2424- );
2525-2626- return res.json();
2727-}
2828-2929-export async function getUpload(uploadId: string): Promise<ApiV1UploadGetResponse | ApiError> {
3030- const res = await fetch(
3131- `${process.env.NEXT_PUBLIC_API}/ai/${uploadId}`,
3232- defaultFetchOptions
3333- );
3434-3535- return res.json();
3636-}
+1-1
app/layout.tsx
···4242export const generateMetadata = (): Metadata => {
43434444 const title = "Wamellow: Next-gen of Discord Bots & Apps";
4545- const description = "Engage with leaderboards, starboards, and welcoming atmosphere. Dive into anime discussions, enjoy free /image AI and unleash the power of Text-To-Speech.";
4545+ const description = "Engage with leaderboards, starboards, and welcoming atmosphere. Dive into anime discussions, enjoy free chat aI and unleash the power of Text-To-Speech.";
46464747 return {
4848 metadataBase: new URL(getBaseUrl()),