The weeb for the next gen discord boat - Wamellow wamellow.com
bot discord
3
fork

Configure Feed

Select the types of activity you want to include in your feed.

add ai home

Luna 60adeea1 cc673c08

+354 -38
+192
app/(home)/ai/page.tsx
··· 1 + import { Code } from "@nextui-org/react"; 2 + import { Metadata } from "next"; 3 + import { Montserrat, Patrick_Hand } from "next/font/google"; 4 + import Image from "next/image"; 5 + import Link from "next/link"; 6 + import { BsDiscord } from "react-icons/bs"; 7 + import { HiChevronRight, HiLightningBolt, HiUserAdd } from "react-icons/hi"; 8 + 9 + import Badge from "@/components/badge"; 10 + import Box from "@/components/box"; 11 + import Highlight from "@/components/discord/markdown"; 12 + import DiscordMessage from "@/components/discord/message"; 13 + import ImageGrid from "@/components/image-grid"; 14 + import ImageReduceMotion from "@/components/image-reduce-motion"; 15 + import { ServerButton } from "@/components/server-button"; 16 + import ArrowPic from "@/public/arroww.webp"; 17 + import { ApiV1AiResponse } from "@/typings"; 18 + import cn from "@/utils/cn"; 19 + import { getBaseUrl, getCanonicalUrl } from "@/utils/urls"; 20 + 21 + const montserrat = Montserrat({ subsets: ["latin"] }); 22 + const handwritten = Patrick_Hand({ subsets: ["latin"], weight: "400" }); 23 + 24 + export const revalidate = 3600; 25 + 26 + const fetchOptions = { headers: { Authorization: process.env.API_SECRET as string }, next: { revalidate: 60 * 60 } }; 27 + 28 + export const generateMetadata = async (): Promise<Metadata> => { 29 + 30 + const title = "Supercharged Ai"; 31 + const description = "Unlock complimentary access to a variety of free image generation models directly within your Discord server."; 32 + const url = getCanonicalUrl("ai"); 33 + 34 + return { 35 + title, 36 + description, 37 + alternates: { 38 + canonical: url 39 + }, 40 + openGraph: { 41 + title, 42 + description, 43 + type: "website", 44 + url, 45 + images: `${getBaseUrl()}/waya-v3.jpg` 46 + }, 47 + twitter: { 48 + card: "summary", 49 + site: "wamellow.com", 50 + title, 51 + description, 52 + images: `${getBaseUrl()}/waya-v3.jpg` 53 + } 54 + }; 55 + }; 56 + 57 + export default async function Home() { 58 + const models = await fetch(`${process.env.NEXT_PUBLIC_API}/ai`, fetchOptions).then((res) => res.json()) as ApiV1AiResponse[]; 59 + const query = "girl below sakura tree"; 60 + 61 + const styles = { 62 + h2: cn(montserrat.className, "lg:text-5xl text-4xl bg-gradient-to-b bg-clip-text text-transparent from-neutral-200 from-40% to-neutral-400 font-bold underline decoration-violet-400"), 63 + h3: cn(montserrat.className, "lg:text-2xl text-xl bg-gradient-to-b bg-clip-text text-transparent from-neutral-200 from-40% to-neutral-300 font-semibold") 64 + }; 65 + 66 + const messageProps = () => { 67 + return { 68 + mode: "DARK" as const, 69 + commandUsed: { 70 + name: "image", 71 + username: "@mwlica", 72 + avatar: "/luna-small.webp", 73 + bot: false 74 + }, 75 + 76 + user: { 77 + username: "Wamellow", 78 + avatar: "/waya-v3-small.webp", 79 + bot: true 80 + } 81 + }; 82 + }; 83 + 84 + return ( 85 + <div className="flex items-center flex-col w-full"> 86 + 87 + <div className="md:text-5xl text-4xl font-semibold md:mb-6 mb-4 dark:text-neutral-100 text-neutral-900 flex gap-2 w-full"> 88 + <h1 className={montserrat.className}> 89 + <span className="bg-gradient-to-r from-indigo-400 to-pink-400 bg-clip-text text-transparent break-keep">Supercharged Ai</span> 90 + </h1> 91 + <HiLightningBolt className="text-pink-400 rotate-6" /> 92 + <Badge text="Free" /> 93 + </div> 94 + 95 + {models && <ImageGrid images={models.slice(0, 24).map((model) => ({ id: model.title, url: model.url || "/discord.webp" }))} />} 96 + 97 + <div className="md:text-xl text-lg lg:flex w-full mt-4"> 98 + <span className="font-medium"> 99 + Unlock complimentary access to a variety of image generation models directly within your Discord server. Powered by LuxuryLabs 100 + </span> 101 + 102 + <div className="flex flex-col min-w-full lg:min-w-[420px]"> 103 + 104 + <div className="lg:ml-auto flex gap-2 mt-4 lg:mt-0"> 105 + <ServerButton 106 + as={Link} 107 + startContent={<HiUserAdd />} 108 + className="w-1/2 lg:w-fit !text-xl !font-medium" 109 + color="secondary" 110 + href="/login?invite=true" 111 + size="lg" 112 + > 113 + <span className="block sm:hidden">Invite</span> 114 + <span className="hidden sm:block">Invite Wamellow</span> 115 + </ServerButton> 116 + <ServerButton 117 + as={Link} 118 + startContent={<BsDiscord />} 119 + className="w-1/2 lg:w-fit !text-xl !font-medium" 120 + href="/support" 121 + size="lg" 122 + > 123 + <span className="block sm:hidden">Support</span> 124 + <span className="hidden sm:block">Join support</span> 125 + </ServerButton> 126 + </div> 127 + 128 + 129 + <span className={`lg:ml-auto flex gap-2 text-neutral-500 font-mediumr ${handwritten.className} mt-3 opacity-80 pl-20 lg:pr-20 rotate-2`}> 130 + <Image src={ArrowPic} width={24} height={24} alt="arrow up" className="h-5 w-5 relative top-px" draggable={false} /> 131 + Get started here in seconds 132 + </span> 133 + 134 + </div> 135 + 136 + </div> 137 + 138 + <div className="lg:mt-14 mt-10" /> 139 + 140 + <div className="w-full"> 141 + <h2 className={styles.h2}>/image command</h2> 142 + <div className="my-8 max-w-2xl font-medium"> 143 + We recommend that you play around with each model yourself as this page uses the same <Code>{query}</Code> query for everything, even non-anime models. 144 + </div> 145 + </div> 146 + 147 + <article itemScope itemType="http://schema.org/Article" className="grid grid-cols-2 gap-6 mb-10 w-full"> 148 + 149 + {models.map((item, i) => ( 150 + <Box key={item.title + i} small className="gap-10 items-center w-full"> 151 + <h3 className={styles.h3}>{item.title}</h3> 152 + <div className="mt-2 mb-6"> 153 + <Code className="select-all" color="secondary">/image query:{query} model:{item.title}</Code> 154 + </div> 155 + 156 + <div className="w-full px-8 py-4 rounded-lg" style={{ backgroundColor: "rgb(43, 45, 49)" }}> 157 + <DiscordMessage {...messageProps()}> 158 + <Highlight mode={"DARK"} text="Please help us on [top.gg](https://top.gg/bot/1125449347451068437/vote), only takes a few seconds" /> 159 + <Image 160 + alt="" 161 + className="rounded-md shadow-md max-w-lg w-full mt-2" 162 + height={512} 163 + itemProp="image" 164 + loading="lazy" 165 + src={item.url} 166 + width={512} 167 + /> 168 + </DiscordMessage> 169 + </div> 170 + </Box> 171 + ))} 172 + </article> 173 + 174 + <div className="w-full mt-6 md:flex gap-4 items-center"> 175 + <div className="flex gap-4 items-center"> 176 + <span className="flex items-center gap-2"> 177 + <ImageReduceMotion url="/luna" size={64} alt="mwlica's profile picture" className="w-12 h-12 rounded-full" /> 178 + <div> 179 + <div className="flex items-center gap-2"> 180 + <span className="text-xl font-medium dark:text-neutral-200 text-neutral-800">@mwlica</span> <Badge text="Developer" /> 181 + </div> 182 + <span className="dark:text-neutral-300 text-neutral-700">Cute femboy</span> 183 + </div> 184 + </span> 185 + <HiChevronRight className="w-8 h-8" /> 186 + </div> 187 + <span className={`${handwritten.className} text-2xl break-words block mt-2`}>„WHY IS THERE A TRAIN LMFAO“</span> 188 + </div> 189 + 190 + </div> 191 + ); 192 + }
+7 -3
app/(home)/bot/pronouns/layout.tsx
··· 5 5 import { BsDiscord } from "react-icons/bs"; 6 6 import { HiChevronRight, HiHome, HiUserAdd } from "react-icons/hi"; 7 7 8 - import ServerGrid from "@/components/guild-grid"; 8 + import ImageGrid from "@/components/image-grid"; 9 9 import ImageReduceMotion from "@/components/image-reduce-motion"; 10 10 import { ServerButton } from "@/components/server-button"; 11 11 import ArrowPic from "@/public/arroww.webp"; ··· 14 14 15 15 const montserrat = Montserrat({ subsets: ["latin"] }); 16 16 const handwritten = Patrick_Hand({ subsets: ["latin"], weight: "400" }); 17 + 18 + export const revalidate = 3600; 19 + 20 + const fetchOptions = { headers: { Authorization: process.env.API_SECRET as string }, next: { revalidate: 60 * 60 } }; 17 21 18 22 export const generateMetadata = (): Metadata => { 19 23 ··· 49 53 }: { 50 54 children: React.ReactNode 51 55 }) { 52 - const topGuilds = await fetch(`${process.env.NEXT_PUBLIC_API}/top-guilds`, { headers: { Authorization: process.env.API_SECRET as string }, next: { revalidate: 60 * 60 } }).then((res) => res.json()) as ApiV1TopguildsGetResponse[]; 56 + const topGuilds = await fetch(`${process.env.NEXT_PUBLIC_API}/top-guilds`, fetchOptions).then((res) => res.json()) as ApiV1TopguildsGetResponse[]; 53 57 54 58 return ( 55 59 <div className="flex items-center flex-col w-full"> ··· 62 66 </h1> 63 67 </div> 64 68 65 - <ServerGrid guilds={topGuilds} /> 69 + {topGuilds && <ImageGrid images={topGuilds.map((guild) => ({ id: guild.name, url: guild.icon || "/discord.webp" }))} />} 66 70 67 71 <div className="md:text-xl text-lg lg:flex w-full mt-4"> 68 72 <div className="font-medium w-full grid grid-cols-2 md:flex flex-wrap h-min gap-2">
+70 -10
app/(home)/page.tsx
··· 11 11 import DiscordMessage from "@/components/discord/message"; 12 12 import DiscordMessageEmbed from "@/components/discord/message-embed"; 13 13 import DiscordMessageFile from "@/components/discord/message-file"; 14 - import ServerGrid from "@/components/guild-grid"; 14 + import ImageGrid from "@/components/image-grid"; 15 15 import { ServerButton } from "@/components/server-button"; 16 + import AiPic from "@/public/ai.webp"; 16 17 import ArrowPic from "@/public/arroww.webp"; 17 18 import LeaderboardPic from "@/public/leaderboard.webp"; 18 19 import SpacePic from "@/public/space.webp"; ··· 95 96 </div> 96 97 </div> 97 98 98 - {topGuilds && <ServerGrid guilds={topGuilds} />} 99 + {topGuilds && <ImageGrid images={topGuilds.map((guild) => ({ id: guild.name, url: guild.icon || "/discord.webp" }))} />} 99 100 100 101 <div className="md:text-xl text-lg lg:flex w-full mt-4"> 101 102 <span className="font-medium"> ··· 166 167 as={Link} 167 168 className="bg-wamellow-light" 168 169 startContent={<HiArrowRight />} 169 - href="/leaderboard/1055188344188973066" 170 + href="/leaderboard/828676951023550495" 170 171 > 171 172 View Leaderboard 172 173 </ServerButton> ··· 351 352 <div className="w-full md:w-1/2 px-8 py-4 rounded-lg" style={{ backgroundColor: "rgb(43, 45, 49)" }}> 352 353 <DiscordMessage {...messageProps("anime")}> 353 354 <Highlight mode={"DARK"} text="Please help us on [top.gg](https://top.gg/bot/1125449347451068437/vote), only takes a few seconds" /> 355 + <Image 356 + alt="" 357 + className="rounded-md shadow-md w-56 sm:w-64 md:w-unset max-w-xs mt-2" 358 + height={512} 359 + itemProp="image" 360 + loading="lazy" 361 + src={WaifuPic} 362 + width={512} 363 + /> 364 + </DiscordMessage> 365 + </div> 366 + </Box> 367 + </div> 354 368 355 - <DiscordMessageEmbed 356 - mode={"DARK"} 357 - color={0xbc7ed4} 358 - classname="max-w-min" 369 + <div> 370 + <h2 className={styles.h2}>Create unique images with Ai 🏳️‍⚧️</h2> 371 + <div className="my-8 max-w-md font-medium"> 372 + Unlock complimentary access to a variety of image generation models directly within your Discord server. Without paying a shit ton to MEE6. 373 + </div> 374 + 375 + <Box className="flex flex-col md:flex-row-reverse gap-10 items-center"> 376 + <div className="md:w-1/2"> 377 + <Badge 378 + before={<HiCash />} 379 + text="100% no money loss" 380 + classname="mr-auto ml-0 mb-4" 381 + /> 382 + <h3 className={styles.h3}>/image command</h3> 383 + <div className="pt-6"> 384 + Summon the enchantment of AI-generated images to your Discord server with our versatile /image command, featuring over 40 distinct custom models. 385 + Elevate your server to a haven for unique and dynamic AI-generated images, ensuring a delightful experience for all enthusiasts of the digital arts. 386 + </div> 387 + <div className="p-4 pb-3 border dark:border-wamellow-alpha border-wamellow-100 rounded-lg my-8"> 388 + <Badge 389 + before={<HiFire />} 390 + text="NSFW Supported" 391 + classname="mr-auto ml-0 mb-2" 392 + /> 393 + <span className="text-base"> 394 + Generate spicy images and more in nsfw marked channels. 395 + </span> 396 + </div> 397 + <div className="flex gap-2 mt-6"> 398 + <Invite /> 399 + <ServerButton 400 + as={Link} 401 + className="bg-wamellow-light" 402 + startContent={<HiArrowRight />} 403 + href="/ai" 359 404 > 360 - <Image src={WaifuPic} itemProp="example anime image" alt="" width={640} height={905} loading="lazy" className="mt-2 rounded-md w-56 sm:w-64 md:w-unset max-w-xs" /> 361 - </DiscordMessageEmbed> 405 + View all models 406 + </ServerButton> 407 + </div> 408 + </div> 409 + 410 + <div className="w-full md:w-1/2 px-8 py-4 rounded-lg" style={{ backgroundColor: "rgb(43, 45, 49)" }}> 411 + <DiscordMessage {...messageProps("image")}> 412 + <Highlight mode={"DARK"} text="Please help us on [top.gg](https://top.gg/bot/1125449347451068437/vote), only takes a few seconds" /> 413 + <Image 414 + alt="" 415 + className="rounded-md shadow-md w-64 sm:w-72 md:w-unset max-w-md mt-2" 416 + height={512} 417 + itemProp="image" 418 + loading="lazy" 419 + src={AiPic} 420 + width={512} 421 + /> 362 422 </DiscordMessage> 363 423 </div> 364 424 </Box> ··· 370 430 Level up your Discord support game with Wamellow{"'"}s custom respones, called tags! 371 431 </div> 372 432 373 - <Box className="flex flex-col md:flex-row-reverse gap-10 items-center"> 433 + <Box className="flex flex-col md:flex-row gap-10 items-center"> 374 434 <div className="md:w-1/2"> 375 435 <Badge 376 436 before={<HiCash />}
+7 -3
app/(home)/pro/page.tsx
··· 6 6 import { IoMdInfinite } from "react-icons/io"; 7 7 8 8 import Badge from "@/components/badge"; 9 - import ServerGrid from "@/components/guild-grid"; 9 + import ImageGrid from "@/components/image-grid"; 10 10 import ImageReduceMotion from "@/components/image-reduce-motion"; 11 11 import { ApiV1TopguildsGetResponse } from "@/typings"; 12 12 import { getBaseUrl, getCanonicalUrl } from "@/utils/urls"; ··· 15 15 const montserrat = Montserrat({ subsets: ["latin"] }); 16 16 const handwritten = Patrick_Hand({ subsets: ["latin"], weight: "400" }); 17 17 18 + export const revalidate = 3600; 19 + 20 + const fetchOptions = { headers: { Authorization: process.env.API_SECRET as string }, next: { revalidate: 60 * 60 } }; 21 + 18 22 export const generateMetadata = async (): Promise<Metadata> => { 19 23 20 24 const title = "Professional experience"; ··· 45 49 }; 46 50 47 51 export default async function Home() { 48 - const topGuilds = await fetch(`${process.env.NEXT_PUBLIC_API}/top-guilds`, { headers: { Authorization: process.env.API_SECRET as string }, next: { revalidate: 60 * 60 } }).then((res) => res.json()) as ApiV1TopguildsGetResponse[]; 52 + const topGuilds = await fetch(`${process.env.NEXT_PUBLIC_API}/top-guilds`, fetchOptions).then((res) => res.json()) as ApiV1TopguildsGetResponse[]; 49 53 50 54 const buttons = ( 51 55 <> ··· 83 87 <Badge text="Not available" /> 84 88 </div> 85 89 86 - <ServerGrid guilds={topGuilds} /> 90 + {topGuilds && <ImageGrid images={topGuilds.map((guild) => ({ id: guild.name, url: guild.icon || "/discord.webp" }))} />} 87 91 88 92 <div className="dark:bg-wamellow bg-wamellow-100 dark:text-neutral-300 text-neutral-700 mt-10 w-full p-4 rounded-xl text-xl"> 89 93
-22
components/guild-grid.tsx
··· 1 - import { ApiV1TopguildsGetResponse } from "@/typings"; 2 - 3 - import ImageReduceMotion from "./image-reduce-motion"; 4 - 5 - interface Props { 6 - guilds: ApiV1TopguildsGetResponse[]; 7 - } 8 - 9 - export default function ServerGrid({ guilds }: Props) { 10 - return ( 11 - <div className="w-full h-52 overflow-hidden rounded-xl"> 12 - <div className="grid grid-flow-col grid-rows-3 w-full md:gap-4 gap-3 rotate-6 relative right-8 bottom-10 md:bottom-20"> 13 - {guilds.map((guild, i) => ( 14 - <div key={"gridGuild-" + guild.name + i} className="md:h-32 h-24 md:w-32 w-24"> 15 - <ImageReduceMotion url={guild.icon?.split(".").slice(0, -1).join(".")} size={128} alt="server" className="rounded-xl" /> 16 - </div> 17 - ))} 18 - 19 - </div> 20 - </div> 21 - ); 22 - }
+44
components/image-grid.tsx
··· 1 + 2 + import Image from "next/image"; 3 + 4 + import ImageReduceMotion from "./image-reduce-motion"; 5 + 6 + interface Props { 7 + images: { 8 + id: string; 9 + url: string; 10 + }[] 11 + } 12 + 13 + export default function ImageGrid({ images }: Props) { 14 + return ( 15 + <div className="w-full h-52 overflow-hidden rounded-xl"> 16 + <div className="grid grid-flow-col grid-rows-3 w-full md:gap-4 gap-3 rotate-6 relative right-8 bottom-10 md:bottom-20"> 17 + {images.map((image, i) => ( 18 + <div key={"imageGrid-" + image.id + i} className="md:h-32 h-24 md:w-32 w-24"> 19 + {image.url.includes("discordapp.net") 20 + ? 21 + <ImageReduceMotion 22 + alt="server" 23 + className="rounded-xl" 24 + url={image.url?.split(".").slice(0, -1).join(".")} 25 + size={128} 26 + /> 27 + : 28 + <Image 29 + alt="image" 30 + className="rounded-xl" 31 + height={128} 32 + itemProp="image" 33 + loading="lazy" 34 + src={image.url} 35 + width={128} 36 + /> 37 + } 38 + </div> 39 + ))} 40 + 41 + </div> 42 + </div> 43 + ); 44 + }
+6
next.config.js
··· 23 23 hostname: "image-api.wamellow.com", 24 24 port: "", 25 25 pathname: "/" 26 + }, 27 + { 28 + protocol: "https", 29 + hostname: "the-net.loves-genshin.lol", 30 + port: "", 31 + pathname: "/images/ai/**" 26 32 } 27 33 ] 28 34 }
public/ai.png

This is a binary file and will not be displayed.

public/ai.webp

This is a binary file and will not be displayed.

+28
typings.ts
··· 320 320 createdAt: Date; 321 321 } 322 322 323 + export interface ApiV1GuildsModulesEmbedmessagelinksGetResponse { 324 + enabled: boolean; 325 + color?: number | null; 326 + display: 0 | 1 | 2; 327 + } 328 + 329 + export interface ApiV1GuildsModulesNsfwModerationGetResponse { 330 + enabled: boolean; 331 + logChannelId: string | null; 332 + /** 333 + * @example 334 + * 0 - Nothing 335 + * 1 - Ban 336 + * 2 - Kick 337 + * 3 - Delete message 338 + */ 339 + punishment: 0 | 1 | 2 | 3; 340 + timeout: number; 341 + 342 + whitelistChannelIds: string[]; 343 + whitelistRoleIds: string[]; 344 + } 345 + 346 + export interface ApiV1AiResponse { 347 + title: string; 348 + url: string; 349 + } 350 + 323 351 export interface PronounsResponse { 324 352 status: number; 325 353 content: string[];