mirror of
https://github.com/koreanbots/core.git
synced 2025-12-13 05:10:24 +00:00
Fix things for next release (#447)
* feat: updated bot name * fix: blocked bot shown * chore: updated api-docs commit hash * feat: showing build info * fix: number not formatted * feat: parsing image tag * docs: updated issue template
This commit is contained in:
parent
e9d7cc38f9
commit
0759e35f2c
9
.github/ISSUE_TEMPLATE/bug_report.md
vendored
9
.github/ISSUE_TEMPLATE/bug_report.md
vendored
@ -19,14 +19,13 @@ assignees: ''
|
||||
|
||||
> 어떤 문제가 발생하나요?
|
||||
|
||||
## 클라이언트 버전
|
||||
## 빌드 버전
|
||||
|
||||
> 클라이언트 버전을 알려주세요!
|
||||
> 클라이언트의 빌드 버전을 알려주세요!
|
||||
|
||||
<!--
|
||||
클라이언트 버전을 가져오실 줄 모르신다면 아래 링크를 참고해주세요
|
||||
|
||||
https://github.com/koreanbots/docs/blob/master/version.md
|
||||
https://koreanbots.dev/debug
|
||||
에서 확인하실 수 있습니다.
|
||||
-->
|
||||
|
||||
## 사양
|
||||
|
||||
@ -12,8 +12,12 @@ WORKDIR /usr/src/app
|
||||
ARG NEXT_PUBLIC_SENTRY_DSN
|
||||
ARG SENTRY_DSN
|
||||
ARG SENTRY_AUTH_TOKEN
|
||||
ARG SOURCE_COMMIT
|
||||
ARG TAG
|
||||
|
||||
ENV NEXT_PUBLIC_SENTRY_DSN $NEXT_PUBLIC_SENTRY_DSN
|
||||
ENV NEXT_PUBLIC_SOURCE_COMMIT $SOURCE_COMMIT
|
||||
ENV NEXT_PUBLIC_TAG $TAG
|
||||
ENV SENTRY_DSN $SENTRY_DSN
|
||||
ENV SENTRY_AUTH_TOKEN $SENTRY_AUTH_TOKEN
|
||||
ENV SENTRY_ORG koreanbots
|
||||
|
||||
2
api-docs
2
api-docs
@ -1 +1 @@
|
||||
Subproject commit fcc3fb57a2bce58703acb6a2e9be4cfe98929427
|
||||
Subproject commit f7d36b42ac19c91a150580309025f439faa5cbbf
|
||||
@ -1,3 +1,3 @@
|
||||
#!/bin/bash
|
||||
|
||||
docker build --build-arg SENTRY_AUTH_TOKEN=$SENTRY_AUTH_TOKEN --build-arg NEXT_PUBLIC_SENTRY_DSN=$NEXT_PUBLIC_SENTRY_DSN --build-arg SENTRY_DSN=$SENTRY_DSN -f $DOCKERFILE_PATH -t $IMAGE_NAME .
|
||||
docker build --build-arg SENTRY_AUTH_TOKEN=$SENTRY_AUTH_TOKEN --build-arg NEXT_PUBLIC_SENTRY_DSN=$NEXT_PUBLIC_SENTRY_DSN --build-arg SENTRY_DSN=$SENTRY_DSN --build-arg SOURCE_COMMIT=$SOURCE_COMMIT --build-arg TAG=$IMAGE_NAME -f $DOCKERFILE_PATH -t $IMAGE_NAME .
|
||||
@ -6,9 +6,10 @@ import { useEffect, useState } from 'react'
|
||||
import { DefaultSeo } from 'next-seo'
|
||||
import { GlobalHotKeys } from 'react-hotkeys'
|
||||
import NProgress from 'nprogress'
|
||||
import Package from '../package.json'
|
||||
|
||||
import Logger from '@utils/Logger'
|
||||
import { handlePWA, parseCookie, systemTheme } from '@utils/Tools'
|
||||
import { handlePWA, parseCookie, parseDockerhubTag, systemTheme } from '@utils/Tools'
|
||||
import { DESCRIPTION, shortcutKeyMap, THEME_COLOR, TITLE } from '@utils/Constants'
|
||||
import { Theme } from '@types'
|
||||
|
||||
@ -39,6 +40,7 @@ const KoreanbotsApp = ({ Component, pageProps, err, cookie }: KoreanbotsProps):
|
||||
'%c' + 'KOREANBOTS',
|
||||
'color: #3366FF; -webkit-text-stroke: 2px black; font-size: 72px; font-weight: bold;'
|
||||
)
|
||||
Logger.debug(`[BUILD INFO] Tag: ${parseDockerhubTag(process.env.NEXT_PUBLIC_TAG)}, Version: v${Package.version}, Hash: ${process.env.NEXT_PUBLIC_SOURCE_COMMIT}`)
|
||||
console.log(
|
||||
'%c' + '이곳에 코드를 붙여넣으면 공격자에게 엑세스 토큰을 넘겨줄 수 있습니다!!',
|
||||
'color: #ff0000; font-size: 20px; font-weight: bold;'
|
||||
|
||||
@ -27,6 +27,7 @@ const Tag = dynamic(() => import('@components/Tag'))
|
||||
const Segment = dynamic(() => import('@components/Segment'))
|
||||
const Advertisement = dynamic(() => import('@components/Advertisement'))
|
||||
const Login = dynamic(() => import('@components/Login'))
|
||||
const Message = dynamic(() => import('@components/Message'))
|
||||
|
||||
const VoteBot: NextPage<VoteBotProps> = ({ data, user, theme, csrfToken }) => {
|
||||
const [ votingStatus, setVotingStatus ] = useState(0)
|
||||
@ -58,39 +59,46 @@ const VoteBot: NextPage<VoteBotProps> = ({ data, user, theme, csrfToken }) => {
|
||||
}
|
||||
]
|
||||
}} />
|
||||
<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>
|
||||
</Link>
|
||||
<Segment className='mb-16 py-8'>
|
||||
<div className='text-center'>
|
||||
<DiscordAvatar userID={data.id} className='mx-auto w-52 h-52 bg-white mb-4' />
|
||||
<Tag text={<span><i className='fas fa-heart text-red-600' /> {data.votes}</span>} dark />
|
||||
<h1 className='text-3xl font-bold mt-3'>{data.name}</h1>
|
||||
<h4 className='text-md mt-1'>12시간마다 다시 투표하실 수 있습니다.</h4>
|
||||
<div className='inline-block mt-2'>
|
||||
{
|
||||
votingStatus === 0 ? <Button onClick={()=> setVotingStatus(1)}>
|
||||
<><i className='far fa-heart text-red-600'/> 하트 추가</>
|
||||
</Button>
|
||||
: votingStatus === 1 ? <Captcha dark={theme === 'dark'} onVerify={async (key) => {
|
||||
const res = await Fetch<{ retryAfter: number }|unknown>(`/bots/${data.id}/vote`, { method: 'POST', body: JSON.stringify({ _csrf: csrfToken, _captcha: key }) })
|
||||
setResult(res)
|
||||
setVotingStatus(2)
|
||||
}}
|
||||
/>
|
||||
: result.code === 200 ? <h2 className='text-2xl font-bold'>해당 봇에 투표했습니다!</h2>
|
||||
: result.code === 429 ? <>
|
||||
<h2 className='text-2xl font-bold'>이미 해당 봇에 투표하였습니다.</h2>
|
||||
<h4 className='text-md mt-1'>{Day(+new Date() + result.data?.retryAfter).fromNow()} 다시 투표하실 수 있습니다.</h4>
|
||||
</>
|
||||
: <p>{result.message}</p>
|
||||
}
|
||||
</div>
|
||||
{
|
||||
data.state === 'blocked' ? <div className='pb-40'>
|
||||
<Message type='error'>
|
||||
<h2 className='text-lg font-black'>해당 봇은 관리자에 의해 삭제되었습니다.</h2>
|
||||
</Message>
|
||||
</div> : <>
|
||||
<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>
|
||||
</Link>
|
||||
<Segment className='mb-16 py-8'>
|
||||
<div className='text-center'>
|
||||
<DiscordAvatar userID={data.id} className='mx-auto w-52 h-52 bg-white mb-4' />
|
||||
<Tag text={<span><i className='fas fa-heart text-red-600' /> {data.votes}</span>} dark />
|
||||
<h1 className='text-3xl font-bold mt-3'>{data.name}</h1>
|
||||
<h4 className='text-md mt-1'>12시간마다 다시 투표하실 수 있습니다.</h4>
|
||||
<div className='inline-block mt-2'>
|
||||
{
|
||||
votingStatus === 0 ? <Button onClick={()=> setVotingStatus(1)}>
|
||||
<><i className='far fa-heart text-red-600'/> 하트 추가</>
|
||||
</Button>
|
||||
: votingStatus === 1 ? <Captcha dark={theme === 'dark'} onVerify={async (key) => {
|
||||
const res = await Fetch<{ retryAfter: number }|unknown>(`/bots/${data.id}/vote`, { method: 'POST', body: JSON.stringify({ _csrf: csrfToken, _captcha: key }) })
|
||||
setResult(res)
|
||||
setVotingStatus(2)
|
||||
}}
|
||||
/>
|
||||
: result.code === 200 ? <h2 className='text-2xl font-bold'>해당 봇에 투표했습니다!</h2>
|
||||
: result.code === 429 ? <>
|
||||
<h2 className='text-2xl font-bold'>이미 해당 봇에 투표하였습니다.</h2>
|
||||
<h4 className='text-md mt-1'>{Day(+new Date() + result.data?.retryAfter).fromNow()} 다시 투표하실 수 있습니다.</h4>
|
||||
</>
|
||||
: <p>{result.message}</p>
|
||||
}
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</Segment>
|
||||
<Advertisement />
|
||||
</div>
|
||||
</Segment>
|
||||
<Advertisement /></>
|
||||
}
|
||||
</Container>
|
||||
}
|
||||
|
||||
|
||||
@ -1,14 +1,13 @@
|
||||
import dynamic from 'next/dynamic'
|
||||
import { useFormik } from 'formik'
|
||||
|
||||
import { checkBrowser } from '@utils/Tools'
|
||||
|
||||
const Container = dynamic(()=> import('@components/Container'))
|
||||
const Divider = dynamic(()=> import('@components/Divider'))
|
||||
const Segment = dynamic(()=> import('@components/Segment'))
|
||||
|
||||
import Package from '../package.json'
|
||||
import Markdown from '@components/Markdown'
|
||||
import { parseDockerhubTag } from '@utils/Tools'
|
||||
|
||||
const ClientInfo = ():JSX.Element => {
|
||||
const formik = useFormik({
|
||||
@ -29,44 +28,18 @@ https://github.com/koreanbots
|
||||
},
|
||||
onSubmit: ()=>{ alert('Pong') }
|
||||
})
|
||||
return <Container paddingTop className='mb-10'>
|
||||
return <Container paddingTop className='pb-10'>
|
||||
<h1 className='text-4xl font-bold mb-3 mt-3'>개발자모드</h1>
|
||||
<h2 className='text-3xl font-semibold mb-4'>정보들</h2>
|
||||
<Segment>
|
||||
<div className='markdown-body text-black dark:text-white'>
|
||||
<h1>빌드정보</h1>
|
||||
<ul className='list-disc'>
|
||||
<li>버전: <code>{Package.version}</code></li>
|
||||
|
||||
<li>
|
||||
해시: <a href={`https://github.com/koreanbots/koreanbots/commit/${process.env.NEXT_PUBLIC_COMMIT_HASH}`}><code>{process.env.NEXT_PUBLIC_COMMIT_HASH}</code></a>
|
||||
</li>
|
||||
<li>브랜치: <code>{process.env.NEXT_PUBLIC_BRANCH}</code></li>
|
||||
|
||||
<li>Tag: <code>{parseDockerhubTag(process.env.NEXT_PUBLIC_TAG)}</code></li>
|
||||
<li>Version: <code>v{Package.version}</code></li>
|
||||
<li>Hash: <code>{process.env.NEXT_PUBLIC_SOURCE_COMMIT}</code></li>
|
||||
</ul>
|
||||
|
||||
<h1>클라이언트 정보</h1>
|
||||
<h2>브라우저</h2>
|
||||
<code>{checkBrowser()}</code>
|
||||
<h2>User-Agent</h2>
|
||||
<pre>{navigator.userAgent}</pre>
|
||||
{/* <h2>Darkmode</h2>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Theme</th>
|
||||
<th>System Cached</th>
|
||||
<th>System</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>{theme}</td>
|
||||
<td>{localStorage.detected}</td>
|
||||
<td>{systemTheme}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table> */}
|
||||
</div>
|
||||
</Segment>
|
||||
<Divider />
|
||||
|
||||
@ -107,7 +107,7 @@ const Users: NextPage<UserProps> = ({ user, data }) => {
|
||||
{data.bots.length === 0 ? <h2 className='text-xl'>소유한 봇이 없습니다.</h2> :
|
||||
<ResponsiveGrid>
|
||||
{
|
||||
(data.bots as Bot[]).map((bot: Bot) => (
|
||||
(data.bots as Bot[]).filter(el => el.state !== 'blocked').map((bot: Bot) => (
|
||||
<BotCard key={bot.id} bot={bot} />
|
||||
))
|
||||
}
|
||||
|
||||
@ -2,6 +2,7 @@ import { DiscordEnpoints } from '../utils/Constants'
|
||||
import { checkUserFlag, formatNumber } from '../utils/Tools'
|
||||
|
||||
test('format Number', () => {
|
||||
expect(formatNumber(995)).toBe('1천')
|
||||
expect(formatNumber(1000)).toBe('1천')
|
||||
expect(formatNumber(33333)).toBe('3.3만')
|
||||
expect(formatNumber(600)).toBe('600')
|
||||
|
||||
@ -57,14 +57,14 @@ async function getBot(id: string, owners=true):Promise<Bot> {
|
||||
res[0].status = discordBot.presence?.activities?.find(r => r.type === 'STREAMING') ? 'streaming' : discordBot.presence?.status || null
|
||||
delete res[0].trusted
|
||||
delete res[0].partnered
|
||||
if (owners)
|
||||
{
|
||||
if (owners) {
|
||||
res[0].owners = await Promise.all(
|
||||
res[0].owners.map(async (u: string) => await get._rawUser.load(u))
|
||||
)
|
||||
res[0].owners = res[0].owners.filter((el: User | null) => el).map((row: User) => ({ ...row }))
|
||||
}
|
||||
|
||||
|
||||
await knex('bots').update({ name: discordBot.username }).where({ id })
|
||||
|
||||
}
|
||||
|
||||
@ -95,28 +95,31 @@ async function getBotList(type: ListType, page = 1, query?: string):Promise<BotL
|
||||
let res: { id: string }[]
|
||||
let count:string|number
|
||||
if (type === 'VOTE') {
|
||||
count = (await knex('bots').count())[0]['count(*)']
|
||||
count = (await knex('bots').whereNot({ state: 'blocked' }).count())[0]['count(*)']
|
||||
res = await knex('bots')
|
||||
.orderBy('votes', 'desc')
|
||||
.orderBy('servers', 'desc')
|
||||
.limit(16)
|
||||
.offset(((page ? Number(page) : 1) - 1) * 16)
|
||||
.select(['id'])
|
||||
.whereNot({ state: 'blocked' })
|
||||
} else if (type === 'TRUSTED') {
|
||||
count = (
|
||||
await knex('bots')
|
||||
.where({ trusted: true })
|
||||
.count()
|
||||
.whereNot({ state: 'blocked' })
|
||||
)[0]['count(*)']
|
||||
res = await knex('bots')
|
||||
res = await knex('bots').whereNot({ state: 'blocked' })
|
||||
.where({ trusted: true })
|
||||
.orderByRaw('RAND()')
|
||||
.limit(16)
|
||||
.offset(((page ? Number(page) : 1) - 1) * 16)
|
||||
.select(['id'])
|
||||
.whereNot({ state: 'blocked' })
|
||||
} else if (type === 'NEW') {
|
||||
count = (
|
||||
await knex('bots')
|
||||
await knex('bots').whereNot({ state: 'blocked' })
|
||||
.count()
|
||||
)[0]['count(*)']
|
||||
res = await knex('bots')
|
||||
@ -124,14 +127,15 @@ async function getBotList(type: ListType, page = 1, query?: string):Promise<BotL
|
||||
.limit(16)
|
||||
.offset(((page ? Number(page) : 1) - 1) * 16)
|
||||
.select(['id'])
|
||||
.whereNot({ state: 'blocked' })
|
||||
} else if (type === 'PARTNERED') {
|
||||
count = (
|
||||
await knex('bots')
|
||||
.where({ partnered: true })
|
||||
.where({ partnered: true }).andWhereNot({ state: 'blocked' })
|
||||
.count()
|
||||
)[0]['count(*)']
|
||||
res = await knex('bots')
|
||||
.where({ partnered: true })
|
||||
.where({ partnered: true }).andWhereNot({ state: 'blocked' })
|
||||
.orderByRaw('RAND()')
|
||||
.limit(16)
|
||||
.offset(((page ? Number(page) : 1) - 1) * 16)
|
||||
@ -141,11 +145,11 @@ async function getBotList(type: ListType, page = 1, query?: string):Promise<BotL
|
||||
if (!categories.includes(query)) throw new Error('알 수 없는 카테고리입니다.')
|
||||
count = (
|
||||
await knex('bots')
|
||||
.where('category', 'like', `%${decodeURI(query)}%`)
|
||||
.where('category', 'like', `%${decodeURI(query)}%`).andWhereNot({ state: 'blocked' })
|
||||
.count()
|
||||
)[0]['count(*)']
|
||||
res = await knex('bots')
|
||||
.where('category', 'like', `%${decodeURI(query)}%`)
|
||||
.where('category', 'like', `%${decodeURI(query)}%`).andWhereNot({ state: 'blocked' })
|
||||
.orderBy('votes', 'desc')
|
||||
.orderBy('servers', 'desc')
|
||||
.limit(16)
|
||||
|
||||
@ -27,11 +27,12 @@ export function formatNumber(value: number):string {
|
||||
if(!value) return '0'
|
||||
const suffixes = ['', '만', '억', '조','해']
|
||||
const suffixNum = Math.floor((''+value).length/4)
|
||||
let shortValue:string|number = parseFloat((suffixNum != 0 ? (value / Math.pow(10000,suffixNum)) : value).toPrecision(2))
|
||||
let shortValue: string|number = parseFloat((suffixNum != 0 ? (value / Math.pow(10000, suffixNum)) : value).toPrecision(2))
|
||||
if (shortValue % 1 != 0) {
|
||||
shortValue = shortValue.toFixed(1)
|
||||
}
|
||||
if(suffixNum === 1 && shortValue < 1) return Number(shortValue) * 10 + '천'
|
||||
else if(shortValue === 1000) return '1천'
|
||||
return shortValue+suffixes[suffixNum]
|
||||
}
|
||||
|
||||
@ -189,4 +190,8 @@ export function getRandom<T=unknown>(arr: T[]): T {
|
||||
return arr[Math.floor(Math.random() * arr.length)]
|
||||
}
|
||||
|
||||
export function parseDockerhubTag(imageTag: string) {
|
||||
return imageTag?.split('/').pop().split(':').pop()
|
||||
}
|
||||
|
||||
export * from './ShowdownExtensions'
|
||||
Loading…
x
Reference in New Issue
Block a user