mirror of
https://github.com/koreanbots/core.git
synced 2025-12-15 14:10:22 +00:00
fix: router instance called at serverside while rendering
This commit is contained in:
parent
7ba2096c31
commit
dcdd7e0710
16
components/Login.tsx
Normal file
16
components/Login.tsx
Normal file
@ -0,0 +1,16 @@
|
||||
import { redirectTo } from '@utils/Tools'
|
||||
import { useRouter } from 'next/router'
|
||||
import { useEffect } from 'react'
|
||||
|
||||
const Login: React.FC = ({ children }) => {
|
||||
const router = useRouter()
|
||||
useEffect(() => {
|
||||
localStorage.redirectTo = window.location.href
|
||||
redirectTo(router, 'login')
|
||||
})
|
||||
return <>
|
||||
{children}
|
||||
</>
|
||||
}
|
||||
|
||||
export default Login
|
||||
@ -1,4 +1,4 @@
|
||||
import { ReactNode } from 'react'
|
||||
import { ReactNode, useEffect } from 'react'
|
||||
import dynamic from 'next/dynamic'
|
||||
import { useRouter } from 'next/router'
|
||||
|
||||
@ -6,22 +6,25 @@ import { redirectTo } from '@utils/Tools'
|
||||
|
||||
const Container = dynamic(() => import('@components/Container'))
|
||||
|
||||
const Redirect = ({ to, children }:RedirectProps):JSX.Element => {
|
||||
const Redirect = ({ to, text=true, children }:RedirectProps):JSX.Element => {
|
||||
const router = useRouter()
|
||||
if(!to) throw new Error('No Link')
|
||||
redirectTo(router, to)
|
||||
useEffect(() => {
|
||||
redirectTo(router, to)
|
||||
}, [])
|
||||
if(children) return <>
|
||||
{children}
|
||||
</>
|
||||
return <Container paddingTop>
|
||||
<div>
|
||||
<a href={to} className='text-blue-400'>자동으로 리다이렉트되지 않는다면 클릭해세요.</a>
|
||||
<a href={to} className='text-blue-400'>{text && '자동으로 리다이렉트되지 않는다면 클릭해세요.'}</a>
|
||||
</div>
|
||||
</Container>
|
||||
}
|
||||
|
||||
interface RedirectProps {
|
||||
to: string
|
||||
text?: boolean
|
||||
children?: ReactNode
|
||||
}
|
||||
|
||||
|
||||
@ -35,6 +35,7 @@ const Button = dynamic(() => import('@components/Button'))
|
||||
const TextArea = dynamic(() => import('@components/Form/TextArea'))
|
||||
const Modal = dynamic(() => import('@components/Modal'))
|
||||
const NSFW = dynamic(() => import('@components/NSFW'))
|
||||
const Login = dynamic(() => import('@components/Login'))
|
||||
|
||||
const Bots: NextPage<BotsProps> = ({ data, desc, date, user, theme, csrfToken }) => {
|
||||
const bg = checkBotFlag(data?.flags, 'trusted') && data?.banner
|
||||
@ -42,10 +43,6 @@ const Bots: NextPage<BotsProps> = ({ data, desc, date, user, theme, csrfToken })
|
||||
const [ nsfw, setNSFW ] = useState<boolean>()
|
||||
const [ reportModal, setReportModal ] = useState(false)
|
||||
const [ reportRes, setReportRes ] = useState<ResponseProps<null>>(null)
|
||||
function toLogin() {
|
||||
localStorage.redirectTo = window.location.href
|
||||
redirectTo(router, 'login')
|
||||
}
|
||||
useEffect(() => {
|
||||
setNSFW(localStorage.nsfw)
|
||||
}, [])
|
||||
@ -188,7 +185,7 @@ const Bots: NextPage<BotsProps> = ({ data, desc, date, user, theme, csrfToken })
|
||||
))}
|
||||
<div className='list grid'>
|
||||
<a className='text-red-600 hover:underline cursor-pointer' onClick={() => {
|
||||
if(!user) toLogin()
|
||||
if(!user) return <Login />
|
||||
else setReportModal(true)
|
||||
}} aria-hidden='true'>
|
||||
<i className='far fa-flag' />
|
||||
|
||||
@ -5,7 +5,7 @@ import { useRouter } from 'next/router'
|
||||
|
||||
import { Bot, CsrfContext, ResponseProps, Theme, User } from '@types'
|
||||
import { get } from '@utils/Query'
|
||||
import { makeBotURL, parseCookie, checkBotFlag, redirectTo } from '@utils/Tools'
|
||||
import { makeBotURL, parseCookie, checkBotFlag } from '@utils/Tools'
|
||||
|
||||
import { ParsedUrlQuery } from 'querystring'
|
||||
|
||||
@ -16,6 +16,7 @@ import { useState } from 'react'
|
||||
import Fetch from '@utils/Fetch'
|
||||
import Day from '@utils/Day'
|
||||
import { getJosaPicker } from 'josa'
|
||||
import { KoreanbotsEndPoints } from '@utils/Constants'
|
||||
|
||||
|
||||
const Container = dynamic(() => import('@components/Container'))
|
||||
@ -25,6 +26,7 @@ const Tag = dynamic(() => import('@components/Tag'))
|
||||
const Segment = dynamic(() => import('@components/Segment'))
|
||||
const SEO = dynamic(() => import('@components/SEO'))
|
||||
const Advertisement = dynamic(() => import('@components/Advertisement'))
|
||||
const Login = dynamic(() => import('@components/Login'))
|
||||
|
||||
const VoteBot: NextPage<VoteBotProps> = ({ data, user, csrfToken, theme }) => {
|
||||
const [ votingStatus, setVotingStatus ] = useState(0)
|
||||
@ -35,18 +37,13 @@ const VoteBot: NextPage<VoteBotProps> = ({ data, user, csrfToken, theme }) => {
|
||||
router.push(`/bots/${data.id}`)
|
||||
return <></>
|
||||
}
|
||||
if(!user) {
|
||||
localStorage.redirectTo = window.location.href
|
||||
redirectTo(router, 'login')
|
||||
return <SEO title='새로운 봇 추가하기' description='자신의 봇을 한국 디스코드봇 리스트에 등록하세요.'/>
|
||||
}
|
||||
if(!user) return <Login>
|
||||
<SEO title={data.name} description={`한국 디스코드봇 리스트에서 ${data.name}에 투표하세요`} image={KoreanbotsEndPoints.CDN.avatar(data.id, { format: 'png', size: 256 })} />
|
||||
</Login>
|
||||
|
||||
if((checkBotFlag(data.flags, 'trusted') || checkBotFlag(data.flags, 'partnered')) && data.vanity && data.vanity !== router.query.id) router.push(`/bots/${data.vanity}/vote?csrfToken=${csrfToken}`)
|
||||
return <Container paddingTop className='py-10'>
|
||||
<SEO title={data.name} description={`한국 디스코드봇 리스트에서 ${data.name}에 투표하세요`} image={
|
||||
data.avatar
|
||||
? `https://cdn.discordapp.com/avatars/${data.id}/${data.avatar}.png?size=1024`
|
||||
: `https://cdn.discordapp.com/embed/avatars/${Number(data.tag) % 5}.png?size=1024`
|
||||
} />
|
||||
<SEO title={data.name} description={`한국 디스코드봇 리스트에서 ${data.name}에 투표하세요`} image={KoreanbotsEndPoints.CDN.avatar(data.id, { format: 'png', size: 256 })} />
|
||||
<Advertisement />
|
||||
<Link href={makeBotURL(data)}>
|
||||
<a className='text-blue-500 hover:opacity-80'><i className='fas fa-arrow-left mt-3 mb-3' /> <strong>{data.name}</strong>{getJosaPicker('로')(data.name)} 돌아가기</a>
|
||||
|
||||
@ -1,22 +1,20 @@
|
||||
import { NextPage, NextPageContext } from 'next'
|
||||
import dynamic from 'next/dynamic'
|
||||
import { useRouter } from 'next/router'
|
||||
|
||||
import { get } from '@utils/Query'
|
||||
import { parseCookie, redirectTo } from '@utils/Tools'
|
||||
import { parseCookie } from '@utils/Tools'
|
||||
|
||||
import { Bot, User } from '@types'
|
||||
|
||||
const Application = dynamic(() => import('@components/Application'))
|
||||
const DeveloperLayout = dynamic(() => import('@components/DeveloperLayout'))
|
||||
const SEO = dynamic(() => import('@components/SEO'))
|
||||
const Login = dynamic(() => import('@components/Login'))
|
||||
|
||||
const Applications: NextPage<ApplicationsProps> = ({ user }) => {
|
||||
const router = useRouter()
|
||||
if(!user) {
|
||||
localStorage.redirectTo = window.location.href
|
||||
redirectTo(router, 'login')
|
||||
return
|
||||
}
|
||||
if(!user) return <Login>
|
||||
<SEO title='한디리 개발자' description='한국 디스코드봇 리스트 API를 활용하여 봇에 다양한 기능을 추가해보세요.' />
|
||||
</Login>
|
||||
return <DeveloperLayout enabled='applications'>
|
||||
<h1 className='text-3xl font-bold'>나의 봇</h1>
|
||||
<p className='text-gray-400'>한국 디스코드봇 리스트 API를 활용하여 봇에 다양한 기능을 추가해보세요.</p>
|
||||
|
||||
@ -35,6 +35,7 @@ const Message = dynamic(() => import('@components/Message'))
|
||||
const Modal = dynamic(() => import('@components/Modal'))
|
||||
const Captcha = dynamic(() => import('@components/Captcha'))
|
||||
const SEO = dynamic(() => import('@components/SEO'))
|
||||
const Login = dynamic(() => import('@components/Login'))
|
||||
|
||||
const ManageBotPage:NextPage<ManageBotProps> = ({ bot, user, csrfToken, theme }) => {
|
||||
const [ data, setData ] = useState(null)
|
||||
@ -42,10 +43,6 @@ const ManageBotPage:NextPage<ManageBotProps> = ({ bot, user, csrfToken, theme })
|
||||
const [ transferModal, setTransferModal ] = useState(false)
|
||||
const [ deleteModal, setDeleteModal ] = useState(false)
|
||||
const router = useRouter()
|
||||
function toLogin() {
|
||||
localStorage.redirectTo = window.location.href
|
||||
redirectTo(router, 'login')
|
||||
}
|
||||
|
||||
async function submitBot(value: ManageBot) {
|
||||
const res = await Fetch(`/bots/${bot.id}`, { method: 'PATCH', body: JSON.stringify(cleanObject<ManageBot>(value)) })
|
||||
@ -59,10 +56,9 @@ const ManageBotPage:NextPage<ManageBotProps> = ({ bot, user, csrfToken, theme })
|
||||
}
|
||||
|
||||
if(!bot) return <NotFound />
|
||||
if(!user) {
|
||||
toLogin()
|
||||
return <SEO title='봇 정보 수정하기' description='봇의 정보를 수정합니다.'/>
|
||||
}
|
||||
if(!user) return <Login>
|
||||
<SEO title='봇 정보 수정하기' description='봇의 정보를 수정합니다.'/>
|
||||
</Login>
|
||||
if(!(bot.owners as User[]).find(el => el.id === user.id) && !checkUserFlag(user.flags, 'staff')) return <Forbidden />
|
||||
return <Container paddingTop className='pt-5 pb-10'>
|
||||
<SEO title={`${bot.name} 수정하기`} description='봇의 정보를 수정합니다.'/>
|
||||
|
||||
@ -4,7 +4,7 @@ import dynamic from 'next/dynamic'
|
||||
import { useRouter } from 'next/router'
|
||||
|
||||
import { get } from '@utils/Query'
|
||||
import { parseCookie, redirectTo } from '@utils/Tools'
|
||||
import { parseCookie } from '@utils/Tools'
|
||||
import { Bot, SubmittedBot, User } from '@types'
|
||||
import Fetch from '@utils/Fetch'
|
||||
import { getToken } from '@utils/Csrf'
|
||||
@ -15,18 +15,14 @@ const ResponsiveGrid = dynamic(() => import('@components/ResponsiveGrid'))
|
||||
const Button = dynamic(() => import('@components/Button'))
|
||||
const BotCard = dynamic(() => import('@components/BotCard'))
|
||||
const SubmittedBotCard = dynamic(() => import('@components/SubmittedBotCard'))
|
||||
const Login = dynamic(() => import('@components/Login'))
|
||||
|
||||
const Panel:NextPage<PanelProps> = ({ logged, user, submits, csrfToken }) => {
|
||||
const router = useRouter()
|
||||
const [ submitLimit, setSubmitLimit ] = useState(8)
|
||||
function toLogin() {
|
||||
localStorage.redirectTo = window.location.href
|
||||
redirectTo(router, 'login')
|
||||
}
|
||||
if(!logged) {
|
||||
toLogin()
|
||||
return <SEO title='관리 패널' />
|
||||
}
|
||||
if(!logged) return <Login>
|
||||
<SEO title='관리 패널' />
|
||||
</Login>
|
||||
return <Container paddingTop className='pt-5 pb-10'>
|
||||
<SEO title='관리 패널' />
|
||||
<h1 className='text-4xl font-bold'>관리 패널</h1>
|
||||
|
||||
@ -1,12 +1,10 @@
|
||||
import { NextPage, NextPageContext } from 'next'
|
||||
import dynamic from 'next/dynamic'
|
||||
import { useRouter } from 'next/router'
|
||||
import { ParsedUrlQuery } from 'querystring'
|
||||
|
||||
import { BotList } from '@types'
|
||||
import { get } from '@utils/Query'
|
||||
import { SearchQuerySchema } from '@utils/Yup'
|
||||
import { redirectTo } from '@utils/Tools'
|
||||
|
||||
|
||||
const Hero = dynamic(() => import('@components/Hero'))
|
||||
@ -16,13 +14,10 @@ const BotCard = dynamic(() => import('@components/BotCard'))
|
||||
const Container = dynamic(() => import('@components/Container'))
|
||||
const ResponsiveGrid = dynamic(() => import('@components/ResponsiveGrid'))
|
||||
const Paginator = dynamic(() => import('@components/Paginator'))
|
||||
const Redirect = dynamic(() => import('@components/Redirect'))
|
||||
|
||||
const Search:NextPage<SearchProps> = ({ data, query }) => {
|
||||
const router = useRouter()
|
||||
if(!query?.q) {
|
||||
redirectTo(router, '/')
|
||||
return <></>
|
||||
}
|
||||
if(!query?.q) return <Redirect text={false} to='/' />
|
||||
return <>
|
||||
<Hero header={`"${query.q}" 검색 결과`} description={`'${query.q}' 에 대한 검색 결과입니다.`} />
|
||||
<SEO title={`"${query.q}" 검색 결과`} description={`'${query.q}' 에 대한 검색 결과입니다.`} />
|
||||
@ -46,6 +41,11 @@ const Search:NextPage<SearchProps> = ({ data, query }) => {
|
||||
}
|
||||
|
||||
export const getServerSideProps = async(ctx: Context) => {
|
||||
if(!ctx.query?.q) {
|
||||
ctx.res.statusCode = 301
|
||||
ctx.res.setHeader('Location', '/')
|
||||
return { props: {} }
|
||||
}
|
||||
let data: BotList
|
||||
if(!ctx.query.page) ctx.query.page = '1'
|
||||
const validate = await SearchQuerySchema.validate(ctx.query).then(el => el).catch(() => null)
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
import { NextPage, NextPageContext } from 'next'
|
||||
import { useState } from 'react'
|
||||
import { useRouter } from 'next/router'
|
||||
import dynamic from 'next/dynamic'
|
||||
import { SnowflakeUtil } from 'discord.js'
|
||||
import { ParsedUrlQuery } from 'querystring'
|
||||
@ -9,7 +8,7 @@ import { Field, Form, Formik } from 'formik'
|
||||
|
||||
import { Bot, User, ResponseProps, Theme } from '@types'
|
||||
import { get } from '@utils/Query'
|
||||
import { checkUserFlag, parseCookie, redirectTo } from '@utils/Tools'
|
||||
import { checkUserFlag, parseCookie } from '@utils/Tools'
|
||||
import { getToken } from '@utils/Csrf'
|
||||
import Fetch from '@utils/Fetch'
|
||||
import { ReportSchema } from '@utils/Yup'
|
||||
@ -30,15 +29,11 @@ const Message = dynamic(() => import('@components/Message'))
|
||||
const Modal = dynamic(() => import('@components/Modal'))
|
||||
const Button = dynamic(() => import('@components/Button'))
|
||||
const TextArea = dynamic(() => import('@components/Form/TextArea'))
|
||||
const Login = dynamic(() => import('@components/Login'))
|
||||
|
||||
const Users: NextPage<UserProps> = ({ user, data, csrfToken, theme }) => {
|
||||
const router = useRouter()
|
||||
const [ reportModal, setReportModal ] = useState(false)
|
||||
const [ reportRes, setReportRes ] = useState<ResponseProps<null>>(null)
|
||||
function toLogin() {
|
||||
localStorage.redirectTo = window.location.href
|
||||
redirectTo(router, 'login')
|
||||
}
|
||||
if (!data?.id) return <NotFound />
|
||||
return (
|
||||
<Container paddingTop className='py-10'>
|
||||
@ -92,7 +87,7 @@ const Users: NextPage<UserProps> = ({ user, data, csrfToken, theme }) => {
|
||||
)}
|
||||
<div className='list-none mt-2'>
|
||||
<a className='text-red-600 hover:underline cursor-pointer' onClick={() => {
|
||||
if(!user) toLogin()
|
||||
if(!user) return <Login />
|
||||
else setReportModal(true)
|
||||
}} aria-hidden='true'>
|
||||
<i className='far fa-flag' />
|
||||
|
||||
@ -103,7 +103,8 @@ export function bufferToStream(binary: Buffer) {
|
||||
return readableInstanceStream
|
||||
}
|
||||
|
||||
export function parseCookie(req: { headers: { cookie?: string }}): { [key: string]: string } {
|
||||
export function parseCookie(req?: { headers: { cookie?: string }}): { [key: string]: string } {
|
||||
if(!req) return {}
|
||||
return cookie.parse(req.headers.cookie || '')
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user