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 updating leaderboards

Luna 05f08c93 eacf6501

+443 -88
+37 -21
app/dashboard/[guildId]/leaderboards/page.tsx
··· 4 4 import { useEffect, useState } from "react"; 5 5 import { HiChartBar } from "react-icons/hi"; 6 6 7 - import { guildStore } from "@/common/guilds"; 7 + import { Guild, guildStore } from "@/common/guilds"; 8 8 import { webStore } from "@/common/webstore"; 9 9 import ErrorBanner from "@/components/Error"; 10 10 import ImageUrlInput from "@/components/inputs/ImageUrlInput"; ··· 12 12 import { ApiV1GuildsModulesLeaderboardGetResponse, RouteErrorResponse } from "@/typings"; 13 13 14 14 import OverviewLinkComponent from "../../../../components/OverviewLinkComponent"; 15 + import UpdatingLeaderboardCard from "./updating.component"; 15 16 16 17 export default function Home() { 17 18 const guild = guildStore((g) => g); ··· 52 53 53 54 }, []); 54 55 55 - if (leaderboard === undefined) return ( 56 - <div> 57 - {error && <ErrorBanner message={error} />} 58 - </div> 59 - ); 56 + const Betweener = () => { 57 + return ( 58 + <> 59 + <hr className="w-1/2 dark:border-wamellow-light border-wamellow-100-light rounded-full select-none md:hidden" /> 60 + <span className="w-0.5 h-20 dark:bg-wamellow-light bg-wamellow-100-light rounded-full rotate-6 select-none hidden md:block" /> 61 + </> 62 + ); 63 + }; 64 + 65 + if (error) return <ErrorBanner message={error} />; 66 + if (!leaderboard) return <></>; 60 67 61 68 return ( 62 69 <div> 63 70 71 + <OverviewLinkComponent 72 + title="View Leaderboard" 73 + message="Easily access and view the top chatters, voice timers, and inviters from this server in the web." 74 + url={`/leaderboard/${params.guildId}`} 75 + icon={<HiChartBar />} 76 + /> 77 + 64 78 <div className={`flex gap-4 border-2 border-violet-400 p-4 mb-4 rounded-lg ${!web.devToolsEnabled && "opacity-50 cursor-not-allowed"}`}> 65 79 66 80 <div className="lg:w-1/2 flex gap-2 w-full"> 67 81 68 82 <div className="w-1/2"> 69 83 <TextInput 70 - name="Text Color" 84 + name="Text" 71 85 url={`/guilds/${guild?.id}/modules/leaderboard`} 72 86 dataName="textColor" 73 87 description="Color used for text." 74 88 type="color" 75 - __defaultState={leaderboard?.textColor ?? 0xe5e5e5} 89 + defaultState={leaderboard?.textColor ?? 0xe5e5e5} 76 90 resetState={0xe5e5e5} 77 91 disabled={!web.devToolsEnabled} 78 92 /> ··· 80 94 81 95 <div className="w-1/2"> 82 96 <TextInput 83 - name="Accent Color" 97 + name="Accent" 84 98 url={`/guilds/${guild?.id}/modules/leaderboard`} 85 99 dataName="accentColor" 86 100 description="Color used for secondary text." 87 101 type="color" 88 - __defaultState={leaderboard?.accentColor ?? 0x8b5cf6} 102 + defaultState={leaderboard?.accentColor ?? 0x8b5cf6} 89 103 resetState={0x8b5cf6} 90 104 disabled={!web.devToolsEnabled} 91 105 /> ··· 95 109 96 110 <div className="w-1/2"> 97 111 <TextInput 98 - name="Background Color" 112 + name="Background" 99 113 url={`/guilds/${guild?.id}/modules/leaderboard`} 100 114 dataName="backgroundColor" 101 115 description="Color used for the background." 102 116 type="color" 103 - __defaultState={leaderboard?.backgroundColor ?? 0x18191c} 104 - resetState={0x18191c} 117 + defaultState={leaderboard?.backgroundColor ?? 0x0d0f11} 118 + resetState={0x0d0f11} 105 119 disabled={!web.devToolsEnabled} 106 120 /> 107 121 </div> ··· 114 128 ratio="aspect-[4/1]" 115 129 dataName="banner" 116 130 description="Enter a url which should be the banner of the leaderboard web page. The recomended image ration is 4:1 and recommended resolution 1024x256px." 117 - __defaultState={leaderboard.banner || ""} 131 + defaultState={leaderboard.banner || ""} 118 132 /> 119 133 120 - <OverviewLinkComponent 121 - className="mt-8" 122 - title="View Leaderboard" 123 - message="Easily access and view the top chatters, voice timers, and inviters from this server in the web." 124 - url={`/leaderboard/${params.guildId}`} 125 - icon={<HiChartBar />} 126 - /> 134 + <hr className="my-6 dark:border-wamellow-light border-wamellow-100-light" /> 135 + 136 + <div className="w-full grid gap-4 md:flex md:gap-0 md:items-center"> 137 + <UpdatingLeaderboardCard guild={guild as Guild} lb={leaderboard.updating.find((lb) => lb.type === "messages")} type="messages" /> 138 + <Betweener /> 139 + <UpdatingLeaderboardCard guild={guild as Guild} lb={leaderboard.updating.find((lb) => lb.type === "voiceminutes")} type="voiceminutes" /> 140 + <Betweener /> 141 + <UpdatingLeaderboardCard guild={guild as Guild} lb={leaderboard.updating.find((lb) => lb.type === "invites")} type="invites" /> 142 + </div> 127 143 128 144 </div > 129 145 );
+284
app/dashboard/[guildId]/leaderboards/updating.component.tsx
··· 1 + "use client"; 2 + import { Tab, Tabs } from "@nextui-org/react"; 3 + import Image from "next/image"; 4 + import Link from "next/link"; 5 + import { FunctionComponent, useState } from "react"; 6 + import { HiExternalLink, HiPencil, HiTrash } from "react-icons/hi"; 7 + 8 + import { Guild } from "@/common/guilds"; 9 + import { webStore } from "@/common/webstore"; 10 + import SelectInput from "@/components/inputs/SelectMenu"; 11 + import Switch from "@/components/inputs/Switch"; 12 + import Modal from "@/components/Modal"; 13 + import { ApiV1GuildsModulesLeaderboardUpdatingPostResponse } from "@/typings"; 14 + 15 + interface Props { 16 + guild: Guild; 17 + lb: ApiV1GuildsModulesLeaderboardUpdatingPostResponse | undefined; 18 + type: "messages" | "voiceminutes" | "invites"; 19 + } 20 + 21 + enum ModalType { 22 + CreateAndEdit = 1, 23 + Delete = 2 24 + } 25 + 26 + const UpdatingLeaderboardCard: FunctionComponent<Props> = ({ guild, lb, type }) => { 27 + const web = webStore((w) => w); 28 + 29 + const [leaderboard, setLeaderboard] = useState(lb); 30 + const [modal, setModal] = useState<ModalType | undefined>(undefined); 31 + 32 + const [channelId, setChannelId] = useState(leaderboard?.channelId); 33 + const [structure, setStructure] = useState(leaderboard?.structure); 34 + const [emoji, setEmoji] = useState(leaderboard?.emoji); 35 + const [styles, setStyles] = useState<ApiV1GuildsModulesLeaderboardUpdatingPostResponse["styles"]>(leaderboard?.styles || { useQuotes: false, rank: null, number: null, user: null }); 36 + 37 + const stylesList = [ 38 + { name: "Bold", value: "**" }, 39 + { name: "Italic", value: "*" }, 40 + { name: "Unerline", value: "__" }, 41 + { name: "Code", value: "`" }, 42 + { name: "None", value: null } 43 + ]; 44 + 45 + const { locale } = Intl.DateTimeFormat().resolvedOptions(); 46 + const time = new Intl.DateTimeFormat(locale, { 47 + year: "numeric", 48 + month: "2-digit", 49 + day: "2-digit", 50 + hour: "2-digit", 51 + minute: "2-digit", 52 + second: "2-digit" 53 + }); 54 + 55 + return ( 56 + <div className="w-1/3 flex items-center flex-col"> 57 + <div> 58 + <div className="text-sm mb-0.5">Updating {type} {leaderboard?.channelId && "in"}</div> 59 + 60 + {leaderboard?.channelId && 61 + <Link 62 + target="_blank" rel="noopener noreferrer" 63 + href={`https://discord.com/channels/${leaderboard?.guildId}/${leaderboard?.channelId}/${leaderboard?.messageId}`} 64 + className="text-2xl dark:text-neutral-100 text-neutral-900 font-medium flex items-center gap-2 group" 65 + > 66 + #{guild?.channels?.find((c) => c.id === leaderboard?.channelId)?.name} 67 + <HiExternalLink className="group-hover:opacity-100 opacity-0 dark:text-neutral-300 text-neutral-700 h-5 w-5" /> 68 + </Link> 69 + } 70 + 71 + <div className="flex items-center gap-2"> 72 + <button 73 + onClick={() => setModal(ModalType.CreateAndEdit)} 74 + className="flex dark:text-violet-400/60 dark:hover:text-violet-400/90 text-violet-600/60 hover:text-violet-600/90 duration-200" 75 + > 76 + <HiPencil className="h-4 w-4 relative top-1" /> 77 + <span className="ml-1">{leaderboard?.channelId ? "Edit" : "Create"} leaderboard</span> 78 + </button> 79 + 80 + {leaderboard?.channelId && web.devToolsEnabled && 81 + <button 82 + onClick={() => setModal(ModalType.Delete)} 83 + className="flex dark:text-red-400/60 dark:hover:text-red-400/90 text-red-600/60 hover:text-red-600/90 duration-200" 84 + > 85 + <HiTrash className="h-5 w-5" /> 86 + <span className="ml-1">Delete</span> 87 + </button> 88 + } 89 + </div> 90 + 91 + </div> 92 + 93 + <Modal 94 + className="flex flex-col gap-3" 95 + title={`${type.replace(/^\w/, (match) => match.toUpperCase())} leaderboard`} 96 + show={modal === ModalType.CreateAndEdit && !!guild} 97 + onClose={() => { 98 + setModal(undefined); 99 + }} 100 + onSubmit={() => { 101 + return fetch(`${process.env.NEXT_PUBLIC_API}/guilds/${guild?.id}/modules/leaderboard/updating`, { 102 + method: "POST", 103 + headers: { 104 + "Content-Type": "application/json", 105 + authorization: localStorage.getItem("token") as string 106 + }, 107 + body: JSON.stringify({ 108 + type, 109 + channelId, 110 + structure, 111 + emoji, 112 + styles 113 + }) 114 + }); 115 + }} 116 + onSuccess={() => { 117 + setLeaderboard({ 118 + ...leaderboard, 119 + type, 120 + // @ts-expect-error it works 121 + channelId, structure, emoji, 122 + styles 123 + }); 124 + }} 125 + subChildren={leaderboard && web.devToolsEnabled && 126 + <div className="text-xs flex flex-col"> 127 + {leaderboard.createdAt && 128 + <span> 129 + <span className="opacity-50">Cr. </span> 130 + {time.format(new Date(leaderboard.createdAt).getTime())} 131 + </span> 132 + } 133 + 134 + {leaderboard.updatedAt && 135 + <span> 136 + <span className="opacity-50">Up. </span> 137 + {time.format(new Date(leaderboard.updatedAt).getTime())} 138 + </span> 139 + } 140 + </div> 141 + } 142 + > 143 + 144 + <SelectInput 145 + name="Channel" 146 + items={guild?.channels?.sort((a, b) => a.name.localeCompare(b.name)).map((c) => { return { name: `#${c.name}`, value: c.id, error: c.missingPermissions.join(", ") }; })} 147 + description="Select a channel where updates should be send into." 148 + defaultState={leaderboard?.channelId || undefined} 149 + onSave={(o) => { 150 + setChannelId(o.value as string); 151 + }} 152 + /> 153 + 154 + <div className="mb-3"> 155 + <div className="text-lg dark:text-neutral-300 text-neutral-700 font-medium mb-1">Leaderboard syle</div> 156 + 157 + <Tabs 158 + aria-label="Display format" 159 + color="secondary" 160 + variant="bordered" 161 + defaultSelectedKey={structure} 162 + onSelectionChange={(i) => setStructure(parseInt(i as string))} 163 + fullWidth 164 + > 165 + <Tab 166 + key="0" 167 + title={ 168 + <div className="flex items-center space-x-2"> 169 + Embed 170 + </div> 171 + } 172 + /> 173 + <Tab 174 + key="1" 175 + title={ 176 + <div className="flex items-center space-x-2"> 177 + Image Grid 178 + </div> 179 + } 180 + /> 181 + <Tab 182 + key="2" 183 + title={ 184 + <div className="flex items-center space-x-2"> 185 + Image List 186 + </div> 187 + } 188 + /> 189 + </Tabs> 190 + </div> 191 + 192 + {structure === 0 && 193 + <div className="flex gap-2"> 194 + <SelectInput 195 + name="Rank" 196 + items={stylesList} 197 + defaultState={leaderboard?.styles?.rank || undefined} 198 + onSave={(o) => { 199 + setStyles({ ...styles, rank: o.value as null }); 200 + }} 201 + /> 202 + <SelectInput 203 + name="Number" 204 + items={stylesList} 205 + defaultState={leaderboard?.styles?.number || undefined} 206 + onSave={(o) => { 207 + setStyles({ ...styles, number: o.value as null }); 208 + }} 209 + /> 210 + <SelectInput 211 + name="User" 212 + items={stylesList} 213 + defaultState={leaderboard?.styles?.user || undefined} 214 + onSave={(o) => { 215 + setStyles({ ...styles, user: o.value as null }); 216 + }} 217 + /> 218 + </div> 219 + } 220 + 221 + {structure === 0 && 222 + <SelectInput 223 + name="Emoji" 224 + items={guild?.emojis?.sort((a, b) => a.name.localeCompare(b.name)).map((c) => { 225 + return { icon: <Image src={`https://cdn.discordapp.com/emojis/${c.id}.webp?size=64&quality=lossless`} className="rounded-md h-6 w-6" alt={c.name} height={64} width={64} />, name: c.name.replace(/-|_/g, " "), value: c.id }; 226 + }) || []} 227 + description="Select a emots which will be between shown after the data count." 228 + defaultState={leaderboard?.emoji || undefined} 229 + onSave={(o) => { 230 + setEmoji(o.value as string); 231 + }} 232 + /> 233 + } 234 + 235 + {structure === 0 && 236 + <Switch 237 + name="Use quotes for text" 238 + tickbox 239 + defaultState={leaderboard?.styles?.useQuotes || false} 240 + onSave={(s) => { 241 + setStyles({ ...styles, useQuotes: s }); 242 + }} 243 + /> 244 + } 245 + 246 + </Modal> 247 + 248 + <Modal 249 + className="flex flex-col gap-3" 250 + buttonName="Delete" 251 + variant="danger" 252 + title={`${type.replace(/^\w/, (match) => match.toUpperCase())} leaderboard`} 253 + show={modal === ModalType.Delete && !!guild} 254 + onClose={() => { 255 + setModal(undefined); 256 + }} 257 + onSubmit={() => { 258 + return fetch(`${process.env.NEXT_PUBLIC_API}/guilds/${guild?.id}/modules/leaderboard/updating`, { 259 + method: "DELETE", 260 + headers: { 261 + "Content-Type": "application/json", 262 + authorization: localStorage.getItem("token") as string 263 + }, 264 + body: JSON.stringify({ type }) 265 + }); 266 + }} 267 + onSuccess={() => { 268 + setChannelId(undefined); 269 + setStructure(undefined); 270 + setEmoji(undefined); 271 + setStyles({ useQuotes: false, rank: null, number: null, user: null }); 272 + // @ts-expect-error it works 273 + setLeaderboard({ type, channelId, structure, emoji, styles }); 274 + }} 275 + > 276 + Are you sure you want to delete this from the database? 277 + </Modal> 278 + 279 + </div> 280 + ); 281 + 282 + }; 283 + 284 + export default UpdatingLeaderboardCard;
+2
app/leaderboard/[guildId]/PageComponent.tsx app/leaderboard/[guildId]/login.component.tsx
··· 9 9 const PageComponent: FunctionComponent<{ searchParams: { page: string, type: string }, membersLength: number }> = ({ searchParams, membersLength }) => { 10 10 const user = userStore((s) => s); 11 11 12 + if (!user?.__fetched) return <></>; 13 + 12 14 if (!user?.id) return ( 13 15 <LoginButton 14 16 className="w-full text-center"
-52
app/leaderboard/[guildId]/SideComponent.tsx
··· 1 - "use client"; 2 - import Link from "next/link"; 3 - import { FunctionComponent } from "react"; 4 - import { HiViewGridAdd } from "react-icons/hi"; 5 - 6 - import { webStore } from "@/common/webstore"; 7 - import Badge from "@/components/badge"; 8 - import { CopyToClipboardButton } from "@/components/copyToClipboard"; 9 - import { ApiV1GuildsModulesLeaderboardGetResponse } from "@/typings"; 10 - import { getCanonicalUrl } from "@/utils/urls"; 11 - 12 - const SideComponent: FunctionComponent<{ guildId: string, design: ApiV1GuildsModulesLeaderboardGetResponse }> = ({ guildId, design }) => { 13 - const web = webStore((w) => w); 14 - 15 - return ( 16 - <div className="flex flex-col gap-3"> 17 - 18 - <CopyToClipboardButton 19 - className={design?.backgroundColor ? "dark:bg-wamellow/60 bg-wamellow-100/60 dark:hover:bg-wamellow-light/70 hover:bg-wamellow-100-light/70" : "dark:bg-wamellow bg-wamellow-100 dark:hover:bg-wamellow-light hover:bg-wamellow-100-light"} 20 - text={getCanonicalUrl("leaderboard", guildId)} 21 - /> 22 - 23 - <div className="dark:text-neutral-300 text-neutral-700 p-2 rounded-md"> 24 - <span className="text-xl font-medium dark:text-neutral-100 text-neutral-900">How this works</span> 25 - <hr className="my-2 dark:border-wamellow-light border-wamellow-100-light" /> 26 - 27 - <span className="text-sm">Users are sorted from most to least active for each category, updates once per minute.</span> 28 - 29 - </div> 30 - 31 - {web.devToolsEnabled && 32 - <div className="dark:text-neutral-300 text-neutral-700 p-2 rounded-md"> 33 - <span className="flex items-center gap-2"> 34 - <span className="text-xl font-medium dark:text-neutral-100 text-neutral-900">Admin Tools</span> 35 - <Badge text="Developer" /> 36 - </span> 37 - <hr className="mt-2 mb-3 dark:border-wamellow-light border-wamellow-100-light" /> 38 - 39 - <Link href={getCanonicalUrl("dashboard", guildId)} className={`flex ${design?.backgroundColor ? "dark:bg-wamellow/60 bg-wamellow-100/60 dark:hover:bg-wamellow-light/70 hover:bg-wamellow-100-light/70" : "dark:bg-wamellow bg-wamellow-100 dark:hover:bg-wamellow-light hover:bg-wamellow-100-light"} dark:hover:text-white py-2 px-4 rounded-md duration-200 w-full`}> 40 - <HiViewGridAdd className="relative top-1" /> 41 - <span className="ml-2">Dashboard</span> 42 - </Link> 43 - 44 - </div> 45 - } 46 - 47 - </div> 48 - ); 49 - 50 - }; 51 - 52 - export default SideComponent;
+2 -2
app/leaderboard/[guildId]/page.tsx
··· 8 8 import decimalToRgb from "@/utils/decimalToRgb"; 9 9 import { getCanonicalUrl } from "@/utils/urls"; 10 10 11 - import PageComponent from "./PageComponent"; 12 - import SideComponent from "./SideComponent"; 11 + import PageComponent from "./login.component"; 12 + import SideComponent from "./side.component"; 13 13 14 14 interface LeaderboardProps { params: { guildId: string }, searchParams: { page: string, type: "messages" | "voiceminutes" | "invites" } } 15 15
+89
app/leaderboard/[guildId]/side.component.tsx
··· 1 + "use client"; 2 + import Link from "next/link"; 3 + import { useRouter } from "next/navigation"; 4 + import { FunctionComponent, useState } from "react"; 5 + import { HiShare, HiTrash, HiViewGridAdd } from "react-icons/hi"; 6 + 7 + import { webStore } from "@/common/webstore"; 8 + import Badge from "@/components/badge"; 9 + import { CopyToClipboardButton } from "@/components/copyToClipboard"; 10 + import ErrorBanner from "@/components/Error"; 11 + import Modal from "@/components/Modal"; 12 + import { ApiV1GuildsModulesLeaderboardGetResponse } from "@/typings"; 13 + import { getCanonicalUrl } from "@/utils/urls"; 14 + 15 + const SideComponent: FunctionComponent<{ guildId: string, design: ApiV1GuildsModulesLeaderboardGetResponse }> = ({ guildId, design }) => { 16 + const web = webStore((w) => w); 17 + const router = useRouter(); 18 + 19 + const [modal, setModal] = useState(false); 20 + 21 + return ( 22 + <div className="flex flex-col gap-3"> 23 + 24 + <CopyToClipboardButton 25 + className={design?.backgroundColor ? "dark:bg-wamellow/60 bg-wamellow-100/60 dark:hover:bg-wamellow-light/70 hover:bg-wamellow-100-light/70" : "dark:bg-wamellow bg-wamellow-100"} 26 + text={getCanonicalUrl("leaderboard", guildId)} 27 + icon={<HiShare />} 28 + /> 29 + 30 + {web.devToolsEnabled && 31 + <div className="dark:text-neutral-300 text-neutral-700 py-2 rounded-md"> 32 + <span className="flex items-center gap-2 px-1"> 33 + <span className="text-xl font-medium dark:text-neutral-100 text-neutral-900">Admin tools</span> 34 + <Badge text="Developer" /> 35 + </span> 36 + <hr className="mt-2 mb-3 dark:border-wamellow-light border-wamellow-100-light" /> 37 + 38 + <div className="flex flex-col gap-3"> 39 + <button 40 + onClick={() => setModal(true)} 41 + className={`flex ${design?.backgroundColor ? "dark:bg-wamellow/60 bg-wamellow-100/60 dark:hover:bg-wamellow-light/70 hover:bg-wamellow-100-light/70" : "dark:bg-wamellow bg-wamellow-100 dark:hover:bg-wamellow-light hover:bg-wamellow-100-light"} dark:hover:text-white py-2 px-4 rounded-md duration-200 w-full`} 42 + > 43 + <HiTrash className="relative top-1" /> 44 + <span className="ml-2">Reset member stats</span> 45 + </button> 46 + <Link href={getCanonicalUrl("dashboard", guildId)} className={`flex ${design?.backgroundColor ? "dark:bg-wamellow/60 bg-wamellow-100/60 dark:hover:bg-wamellow-light/70 hover:bg-wamellow-100-light/70" : "dark:bg-wamellow bg-wamellow-100 dark:hover:bg-wamellow-light hover:bg-wamellow-100-light"} dark:hover:text-white py-2 px-4 rounded-md duration-200 w-full`}> 47 + <HiViewGridAdd className="relative top-1" /> 48 + <span className="ml-2">Dashboard</span> 49 + </Link> 50 + </div> 51 + 52 + </div> 53 + } 54 + 55 + <div className="dark:text-neutral-300 text-neutral-700 py-2 rounded-md"> 56 + <span className="text-xl font-medium dark:text-neutral-100 text-neutral-900 px-1">How this works</span> 57 + <hr className="my-2 dark:border-wamellow-light border-wamellow-100-light" /> 58 + 59 + <div className="text-sm px-1">Users are sorted from most to least active for each category, updates once per minute.</div> 60 + </div> 61 + 62 + <Modal 63 + title="Reset @everyone's stats" 64 + buttonName="Reset" 65 + variant="danger" 66 + show={modal} 67 + onClose={() => setModal(false)} 68 + onSubmit={() => { 69 + return fetch(`${process.env.NEXT_PUBLIC_API}/guilds/${guildId}/top-members`, { 70 + method: "DELETE", 71 + headers: { 72 + "Content-Type": "application/json", 73 + authorization: localStorage.getItem("token") as string 74 + } 75 + }); 76 + }} 77 + onSuccess={() => { 78 + router.refresh(); 79 + }} 80 + > 81 + <ErrorBanner message="Takes a few seconds to apply" type="info" removeButton /> 82 + </Modal> 83 + 84 + </div> 85 + ); 86 + 87 + }; 88 + 89 + export default SideComponent;
+1 -1
common/guilds.ts
··· 2 2 3 3 import { ApiV1GuildsChannelsGetResponse, ApiV1GuildsEmojisGetResponse, ApiV1GuildsGetResponse, ApiV1GuildsRolesGetResponse } from "@/typings"; 4 4 5 - interface Guild extends ApiV1GuildsGetResponse { 5 + export interface Guild extends ApiV1GuildsGetResponse { 6 6 channels?: ApiV1GuildsChannelsGetResponse[]; 7 7 roles?: ApiV1GuildsRolesGetResponse[]; 8 8 emojis?: ApiV1GuildsEmojisGetResponse[];
+28 -12
typings.ts
··· 158 158 delete: boolean; 159 159 } 160 160 161 - interface GuildLeaderboardApp { 162 - channel: string | null; 163 - message: string | null; 161 + export interface ApiV1GuildsModulesLeaderboardUpdatingPostResponse { 162 + leaderboardId: string; 163 + guildId: string; 164 164 165 - type: "daily" | "weekly" | "monthly" | "alltime"; 165 + channelId: string; 166 + messageId: string; 167 + 168 + type: "messages" | "voiceminutes" | "invites"; 169 + 170 + /** 171 + * 0 - text based 172 + * 1 - image grid 173 + * 2 - image list 174 + */ 175 + structure: number; 176 + styles: { 177 + useQuotes: boolean; 178 + rank: "**" | "__" | "*" | "`" | null; 179 + number: "**" | "__" | "*" | "`" | null; 180 + user: "**" | "__" | "*" | "`" | null; 181 + } 182 + 183 + range: "daily" | "weekly" | "monthly" | "alltime"; 166 184 display: "tag" | "username" | "nickname" | "id"; 167 185 168 186 background: string | null; 169 187 emoji: string | null; 170 188 171 - cardColor?: number; 172 - textColor?: number; 189 + updatedAt: string; 190 + createdAt: string; 173 191 } 174 192 175 193 export interface ApiV1GuildsModulesLeaderboardGetResponse { 176 194 banner: string | null; 177 195 emoji: string | null; 178 196 179 - backgroundColor?: number; 180 - textColor?: number; 181 - accentColor?: number; 197 + backgroundColor: number | null; 198 + textColor: number | null; 199 + accentColor: number | null; 182 200 183 - messages: GuildLeaderboardApp; 184 - invites: GuildLeaderboardApp; 185 - voice: GuildLeaderboardApp; 201 + updating: ApiV1GuildsModulesLeaderboardUpdatingPostResponse[] 186 202 } 187 203 188 204 export interface ApiV1GuildsModulesPassportGetResponse {