core/pages/users/[id]/index.tsx
2024-12-30 01:56:29 +09:00

179 lines
5.2 KiB
TypeScript

import { NextPage, NextPageContext } from 'next'
import dynamic from 'next/dynamic'
import Link from 'next/link'
import { SnowflakeUtil } from 'discord.js'
import { ParsedUrlQuery } from 'querystring'
import { josa } from 'josa'
import { Bot, User, Theme, Server } from '@types'
import { get } from '@utils/Query'
import { checkUserFlag, parseCookie } from '@utils/Tools'
import { getToken } from '@utils/Csrf'
import NotFound from '../../404'
import { KoreanbotsEndPoints } from '@utils/Constants'
import { NextSeo } from 'next-seo'
import { useRouter } from 'next/router'
const Container = dynamic(() => import('@components/Container'))
const DiscordAvatar = dynamic(() => import('@components/DiscordAvatar'))
const Divider = dynamic(() => import('@components/Divider'))
const BotCard = dynamic(() => import('@components/BotCard'))
const ServerCard = dynamic(() => import('@components/ServerCard'))
const ResponsiveGrid = dynamic(() => import('@components/ResponsiveGrid'))
const Tag = dynamic(() => import('@components/Tag'))
const Advertisement = dynamic(() => import('@components/Advertisement'))
const Tooltip = dynamic(() => import('@components/Tooltip'))
const Users: NextPage<UserProps> = ({ user, data }) => {
const router = useRouter()
if (!data?.id) return <NotFound />
return (
<Container paddingTop className='py-10'>
<NextSeo
title={data.globalName}
description={
data.bots.length === 0
? `${data.globalName}님의 프로필입니다.`
: josa(
`${(data.bots as Bot[])
.slice(0, 5)
.map((el) => el.name)
.join(', ')}#{을} 제작합니다.`
)
}
openGraph={{
images: [
{
url: KoreanbotsEndPoints.CDN.avatar(data.id, { format: 'png', size: 256 }),
width: 256,
height: 256,
alt: 'User Avatar',
},
],
}}
/>
<div className='lg:flex'>
<div className='mx-auto w-3/5 text-center lg:w-1/6'>
<DiscordAvatar size={512} userID={data.id} className='w-full rounded-full' hash={data.avatar} />
</div>
<div className='w-full grow px-5 py-10 text-center lg:w-5/12 lg:text-left'>
<div>
{data.tag !== '0' ? (
<div className='mb-1 mt-3 lg:flex '>
<h1 className='text-4xl font-bold'>{data.username}</h1>
<span className='ml-0.5 mt-1 text-3xl font-semibold text-gray-400'>
#{data.tag}
</span>
</div>
) : (
<div className='mb-1 mt-3 flex-col lg:flex'>
<h1 className='text-4xl font-bold'>{data.globalName}</h1>
<span className='mt-1 text-2xl font-semibold text-gray-400'>@{data.username}</span>
</div>
)}
<div className='badges mb-2 flex justify-center lg:justify-start'>
{checkUserFlag(data.flags, 'staff') && (
<Tooltip text='한국 디스코드 리스트 스탭입니다.' direction='left'>
<div className='pr-5 text-2xl text-koreanbots-blue'>
<i className='fas fa-hammer' />
</div>
</Tooltip>
)}
{checkUserFlag(data.flags, 'bughunter') && (
<Tooltip text='버그를 많이 제보해주신 분입니다.' direction='left'>
<div className='pr-5 text-2xl text-emerald-500'>
<i className='fas fa-bug' />
</div>
</Tooltip>
)}
</div>
{data.github && (
<Tag
newTab
text={
<>
<i className='fab fa-github' /> {data.github}
</>
}
github
href={`https://github.com/${data.github}`}
/>
)}
{user?.id !== data.id && (
<div className='mt-2 list-none'>
<Link
href={`/users/${router.query.id}/report`}
className='cursor-pointer text-red-600 hover:underline'
aria-hidden='true'
>
<i className='far fa-flag' />
</Link>
</div>
)}
</div>
</div>
</div>
<Divider />
<h2 className='mt-8 pb-4 text-3xl font-bold'> </h2>
{data.bots.length === 0 ? (
<h2 className='text-xl'> .</h2>
) : (
<ResponsiveGrid>
{(data.bots as Bot[])
.filter((el) => el.state !== 'blocked')
.map((bot: Bot) => (
<BotCard key={bot.id} bot={bot} />
))}
</ResponsiveGrid>
)}
<h2 className='py-4 text-3xl font-bold'> </h2>
{data.servers.length === 0 ? (
<h2 className='text-xl'> .</h2>
) : (
<ResponsiveGrid>
{(data.servers as Server[]).map((server: Server) => (
<ServerCard type='list' key={server.id} server={server} />
))}
</ResponsiveGrid>
)}
<Advertisement />
</Container>
)
}
export const getServerSideProps = async (ctx: Context) => {
const parsed = parseCookie(ctx.req)
const user = (await get.Authorization(parsed?.token)) || ''
const data = await get.user.load(ctx.query.id)
return {
props: {
user: (await get.user.load(user)) || {},
data,
date: Number(SnowflakeUtil.deconstruct(data?.id ?? '0')?.timestamp),
csrfToken: getToken(ctx.req, ctx.res),
},
}
}
interface UserProps {
user: User
data: User
csrfToken: string
theme: Theme
}
interface Context extends NextPageContext {
query: URLQuery
}
interface URLQuery extends ParsedUrlQuery {
id: string
}
export default Users