Compare commits

..

No commits in common. "8a96148245e395021469d91eb2b3f21c3b75ccb4" and "843e4137cb8931ba235585008f8fee52bba2184c" have entirely different histories.

11 changed files with 46 additions and 178 deletions

View File

@ -21,7 +21,7 @@ const Label: React.FC<LabelProps> = ({
<span className='align-text-top text-base font-semibold text-red-500'> *</span>
)}
</h3>
<span className='whitespace-pre-line'>{labelDesc}</span>
{labelDesc}
</div>
)}
<div className={short ? 'col-span-1' : 'col-span-3'}>

View File

@ -109,10 +109,7 @@ const Select: React.FC<SelectProps> = ({
onChange={handleChange}
onBlur={handleTouch}
noOptionsMessage={() => '검색 결과가 없습니다.'}
value={values.map((el) => ({
label: Object.values(options).find(({ value }) => value === el)?.label || el,
value: el,
}))}
value={values.map((el) => ({ label: el, value: el }))}
components={{
MultiValue,
MultiValueRemove,

View File

@ -1,6 +1,6 @@
{
"name": "koreanbots",
"version": "2.12.0",
"version": "2.11.0",
"private": true,
"scripts": {
"dev": "next dev",

View File

@ -10,7 +10,7 @@ import HCaptcha from '@hcaptcha/react-hcaptcha'
import { get } from '@utils/Query'
import { cleanObject, parseCookie, redirectTo } from '@utils/Tools'
import { AddBotSubmit, AddBotSubmitSchema } from '@utils/Yup'
import { botCategories, botCategoryDescription, botEnforcements, library } from '@utils/Constants'
import { botCategories, botCategoryDescription, library } from '@utils/Constants'
import { getToken } from '@utils/Csrf'
import Fetch from '@utils/Fetch'
import { ResponseProps, SubmittedBot, Theme, User } from '@types'
@ -57,7 +57,6 @@ const AddBot: NextPage<AddBotProps> = ({ logged, user, csrfToken, theme }) => {
-
-
- ?`,
enforcements: [],
_csrf: csrfToken,
_captcha: 'captcha',
}
@ -357,34 +356,6 @@ const AddBot: NextPage<AddBotProps> = ({ logged, user, csrfToken, theme }) => {
</Segment>
</Label>
<Divider />
<Label
For='enforcements'
label='필수 고지 내용'
labelDesc='내용에 해당하는 경우 필수로 선택해야 합니다.'
required
error={
errors.enforcements && touched.enforcements ? (errors.enforcements as string) : null
}
>
<Selects
options={Object.entries(botEnforcements).map(([k, v]) => ({
label: v.label,
value: k,
}))}
handleChange={(value) => {
setFieldValue(
'enforcements',
value.map((v) => v.value)
)
}}
handleTouch={() => setFieldTouched('enforcements', true)}
values={values.enforcements ?? ([] as string[])}
setValues={(value) => {
setFieldValue('enforcements', value)
}}
/>
</Label>
<Divider />
<p className='mb-5 mt-2 text-base'>
<span className='font-semibold text-red-500'> *</span> =
</p>

View File

@ -246,14 +246,14 @@ const Bots = RequestHandler()
errors: ['다른 커스텀 URL로 다시 시도해주세요.'],
})
}
if (validated.vanity !== bot.vanity) {
await webhookClients.internal.noticeLog.send({
embeds: [
{
title: '한디리 커스텀 URL 변경',
description: `봇: ${bot.name} - <@${bot.id}> ([${
description: `봇: ${bot.name} - <@${bot.id}> ([${bot.id}](${KoreanbotsEndPoints.URL.bot(
bot.id
}](${KoreanbotsEndPoints.URL.bot(bot.id)}))`,
)}))`,
fields: [
{
name: '이전',
@ -269,7 +269,6 @@ const Bots = RequestHandler()
],
})
}
}
const result = await update.bot(req.query.id, validated)
if (result === 0) return ResponseWrapper(res, { code: 400 })
else {
@ -290,7 +289,6 @@ const Bots = RequestHandler()
category: JSON.stringify(bot.category),
vanity: bot.vanity,
banner: bot.banner,
enforcements: JSON.stringify(bot.enforcements),
bg: bot.bg,
},
{
@ -304,7 +302,6 @@ const Bots = RequestHandler()
category: JSON.stringify(validated.category),
vanity: validated.vanity,
banner: validated.banner,
enforcements: JSON.stringify(validated.enforcements),
bg: validated.bg,
}
)

View File

@ -9,16 +9,9 @@ import { ParsedUrlQuery } from 'querystring'
import { getJosaPicker } from 'josa'
import { get } from '@utils/Query'
import {
checkBotFlag,
checkUserFlag,
cleanObject,
makeBotURL,
parseCookie,
redirectTo,
} from '@utils/Tools'
import { checkBotFlag, checkUserFlag, cleanObject, makeBotURL, parseCookie, redirectTo } from '@utils/Tools'
import { ManageBot, getManageBotSchema } from '@utils/Yup'
import { botCategories, botCategoryDescription, botEnforcements, library } from '@utils/Constants'
import { botCategories, botCategoryDescription, library } from '@utils/Constants'
import { Bot, Theme, User } from '@types'
import { getToken } from '@utils/Csrf'
import Fetch from '@utils/Fetch'
@ -89,7 +82,6 @@ const ManageBotPage: NextPage<ManageBotProps> = ({ bot, user, csrfToken, theme }
prefix: bot.prefix,
library: bot.lib,
category: bot.category,
enforcements: bot.enforcements,
intro: bot.intro,
desc: bot.desc,
website: bot.web,
@ -106,12 +98,8 @@ const ManageBotPage: NextPage<ManageBotProps> = ({ bot, user, csrfToken, theme }
>
{({ errors, touched, values, setFieldTouched, setFieldValue }) => (
<Form>
<div className='text-ceznter md:flex md:text-left'>
<DiscordAvatar
userID={bot.id}
className='mx-auto rounded-full md:mx-1'
hash={bot.avatar}
/>
<div className='text-center md:flex md:text-left'>
<DiscordAvatar userID={bot.id} className='mx-auto rounded-full md:mx-1' hash={bot.avatar}/>
<div className='px-8 py-6 md:w-2/3'>
<h1 className='text-3xl font-bold'>
{bot.name}#{bot.tag}
@ -177,11 +165,7 @@ const ManageBotPage: NextPage<ManageBotProps> = ({ bot, user, csrfToken, theme }
error={errors.category && touched.category ? (errors.category as string) : null}
>
<Selects
options={botCategories.map((el) => ({
label: el,
value: el,
description: botCategoryDescription[el],
}))}
options={botCategories.map((el) => ({ label: el, value: el, description: botCategoryDescription[el] }))}
handleChange={(value) => {
setFieldValue(
'category',
@ -289,26 +273,24 @@ const ManageBotPage: NextPage<ManageBotProps> = ({ bot, user, csrfToken, theme }
<Markdown text={values.desc} />
</Segment>
</Label>
{isPerkAvailable && (
{
isPerkAvailable && (
<>
<Divider />
<h2 className='pt-2 text-2xl font-semibold text-koreanbots-green'>
</h2>
<span className='mt-1 text-sm text-gray-400'>
. ( URL과 /
.)
</span>
<h2 className='pt-2 text-2xl font-semibold text-koreanbots-green'> </h2>
<span className='mt-1 text-sm text-gray-400'> . ( URL과 / .)</span>
<Label
For='vanity'
label='한디리 커스텀 URL'
labelDesc='고유한 커스텀 URL을 설정해주세요.'
error={errors.vanity && touched.vanity ? errors.vanity : null}
>
<div className='flex items-center'>
koreanbots.dev/bots/
<Input name='vanity' placeholder='koreanbots' />
</div>
</Label>
<Label
For='banner'
@ -327,35 +309,8 @@ const ManageBotPage: NextPage<ManageBotProps> = ({ bot, user, csrfToken, theme }
<Input name='bg' placeholder='https://koreanbots.dev/logo.png' />
</Label>
</>
)}
<Divider />
<Label
For='enforcements'
label='필수 고지 내용'
labelDesc='내용에 해당하는 경우 필수로 선택해야 합니다.'
required
error={
errors.enforcements && touched.enforcements ? (errors.enforcements as string) : null
}
>
<Selects
options={Object.entries(botEnforcements).map(([k, v]) => ({
label: v.label,
value: k,
}))}
handleChange={(value) => {
setFieldValue(
'enforcements',
value.map((v) => v.value)
)
}}
handleTouch={() => setFieldTouched('enforcements', true)}
values={values.enforcements ?? ([] as string[])}
setValues={(value) => {
setFieldValue('enforcements', value)
}}
/>
</Label>
}
<Divider />
<p className='mb-5 mt-2 text-base'>
<span className='font-semibold text-red-500'> *</span> =
@ -365,6 +320,7 @@ const ManageBotPage: NextPage<ManageBotProps> = ({ bot, user, csrfToken, theme }
<i className='far fa-save' />
</>
</Button>
</Form>
)}
</Formik>

View File

@ -11,7 +11,7 @@ import { SnowflakeUtil } from 'discord.js'
import { ParsedUrlQuery } from 'querystring'
import { Bot, ResponseProps, Theme, User } from '@types'
import { botEnforcements, git, KoreanbotsEndPoints, reportCats, Status } from '@utils/Constants'
import { git, KoreanbotsEndPoints, reportCats, Status } from '@utils/Constants'
import { get } from '@utils/Query'
import Day from '@utils/Day'
import { ReportSchema } from '@utils/Yup'
@ -116,27 +116,13 @@ const Bots: NextPage<BotsProps> = ({ data, desc, date, user, theme, csrfToken })
.
</p>
</Message>
) : data.enforcements.length > 0 ? (
<Message type='warning'>
<h2 className='text-lg font-extrabold'> .</h2>
<p>
{data.enforcements.map((i) => (
<li key={i}>{botEnforcements[i].description}</li>
))}
</p>
</Message>
) : (
''
)}
</div>
<div className='w-full lg:flex'>
<div className='w-full text-center lg:w-2/12'>
<DiscordAvatar
userID={data.id}
size={256}
className='w-full rounded-full'
hash={data.avatar}
/>
<DiscordAvatar userID={data.id} size={256} className='w-full rounded-full' hash={data.avatar}/>
</div>
<div className='w-full grow px-5 py-12 text-center lg:w-5/12 lg:text-left'>
<Tag
@ -172,7 +158,7 @@ const Bots: NextPage<BotsProps> = ({ data, desc, date, user, theme, csrfToken })
</p>
</div>
<div className='w-full lg:w-1/4'>
{data.state === 'ok' && !checkBotFlag(data.flags, 'private') && (
{(data.state === 'ok' && !checkBotFlag(data.flags, 'private')) && (
<LongButton newTab href={`/bots/${router.query.id}/invite`}>
<h4 className='whitespace-nowrap'>
<i className='fas fa-user-plus text-discord-blurple' />

View File

@ -1,12 +1,9 @@
import { botEnforcements } from '@utils/Constants'
import type { GuildFeature } from 'discord.js'
import type { IncomingMessage } from 'http'
import type { NextPageContext } from 'next'
export type Nullable<T> = T | null
export type ValueOf<T> = T[keyof T]
export interface Bot {
id: string
name: string
@ -28,14 +25,11 @@ export interface Bot {
url: string | null
discord: string | null
vanity: string | null
enforcements: BotEnforcementKeys[]
bg: string
banner: string
owners: User[] | string[]
}
export type BotEnforcementKeys = keyof typeof botEnforcements
export interface RawGuild {
id: string
name: string

View File

@ -120,25 +120,6 @@ export const botCategoryDescription = {
: '게임 "마인크래프트"에 관련된 기능을 다룹니다.',
}
export const botEnforcements = {
JOIN_PARTIALLY_ENFORCED: {
label: '서버 참여가 필요한 기능이 있습니다',
description: '봇의 일부 명령어는 봇의 디스코드 서버에 참여해야 사용할 수 있습니다.',
},
JOIN_ENFORCED: {
label: '서버 참여 없이는 봇의 핵심 기능을 사용할 수 없습니다',
description: '봇의 핵심 기능은 봇의 디스코드 서버에 참여해야 사용할 수 있습니다.',
},
LICENSE_PARTIALLY_ENFORCED: {
label: '유료 구매가 필요한 기능이 있습니다',
description: '봇의 일부 명령어는 유료 구매가 필요합니다.',
},
LICENSE_ENFORCED: {
label: '유료 구매 없이는 봇의 핵심 기능을 사용할 수 없습니다',
description: '유료 구매 없이는 봇의 핵심 기능을 사용할 수 없습니다.',
},
} as const
export const botCategoryIcon = {
: 'fas fa-cogs',
: 'fas fa-music',

View File

@ -62,7 +62,6 @@ async function getBot(id: string, topLevel = true): Promise<Bot> {
'bots.status',
'bots.trusted',
'bots.partnered',
'bots.enforcements',
'bots.discord',
'bots.state',
'bots.vanity',
@ -103,7 +102,7 @@ async function getBot(id: string, topLevel = true): Promise<Bot> {
res.owners = JSON.parse(res.owners)
res.banner = res.banner ? camoUrl(res.banner) : null
res.bg = res.bg ? camoUrl(res.bg) : null
res.enforcements = JSON.parse(res.enforcements ?? '[]')
if (discordBot.flags.bitfield & UserFlags.BotHTTPInteractions) {
res.status = 'online'
} else if (botMember) {
@ -449,7 +448,6 @@ async function getBotSubmit(id: string, date: number): Promise<SubmittedBot> {
'id',
'date',
'category',
'enforcements',
'lib',
'prefix',
'intro',
@ -465,7 +463,6 @@ async function getBotSubmit(id: string, date: number): Promise<SubmittedBot> {
.where({ id, date })
if (res.length === 0) return null
res[0].category = JSON.parse(res[0].category)
res[0].enforcements = JSON.parse(res[0].enforcements || '[]')
res[0].owner = await get.user.load(res[0].owner)
return res[0]
}
@ -477,7 +474,6 @@ async function getBotSubmits(id: string): Promise<SubmittedBot[]> {
'id',
'date',
'category',
'enforcements',
'lib',
'prefix',
'intro',
@ -496,7 +492,6 @@ async function getBotSubmits(id: string): Promise<SubmittedBot[]> {
res = await Promise.all(
res.map(async (el) => {
el.category = JSON.parse(el.category)
el.enforcements = JSON.parse(el.enforcements)
el.owner = owner
return el
})
@ -641,7 +636,6 @@ async function submitBot(
git: data.git,
url: data.url,
category: JSON.stringify(data.category),
enforcements: JSON.stringify(data.enforcements),
discord: data.discord,
state: 0,
})
@ -751,7 +745,6 @@ async function updateBot(id: string, data: ManageBot): Promise<number> {
intro: data.intro,
desc: data.desc,
vanity: data.vanity,
enforcements: JSON.stringify(data.enforcements),
banner: data.banner,
bg: data.bg,
})
@ -1141,7 +1134,6 @@ async function approveBotSubmission(id: string, date: number) {
'id',
'date',
'category',
'enforcements',
'lib',
'prefix',
'intro',
@ -1168,7 +1160,6 @@ async function approveBotSubmission(id: string, date: number) {
web: data.web,
git: data.git,
category: data.category,
enforcements: data.enforcements,
discord: data.discord,
token: sign({ id }),
})

View File

@ -3,7 +3,6 @@ import YupKorean from 'yup-locales-ko'
import { ListType } from '@types'
import {
botCategories,
botEnforcements,
library,
reportCats,
reservedVanityBypass,
@ -175,7 +174,6 @@ export const AddBotSubmitSchema: Yup.SchemaOf<AddBotSubmit> = Yup.object({
.min(100, '봇 설명은 최소 100자여야합니다.')
.max(1500, '봇 설명은 최대 1500자여야합니다.')
.required('봇 설명은 필수 항목입니다.'),
enforcements: Yup.array(Yup.string().oneOf(Object.keys(botEnforcements))),
_csrf: Yup.string().required(),
_captcha: Yup.string().required(),
})
@ -192,7 +190,6 @@ export interface AddBotSubmit {
category: string | string[]
intro: string
desc: string
enforcements: string[]
_csrf: string
_captcha: string
}
@ -306,7 +303,6 @@ export function getManageBotSchema(perkAvailable = false) {
.min(100, '봇 설명은 최소 100자여야합니다.')
.max(1500, '봇 설명은 최대 1500자여야합니다.')
.required('봇 설명은 필수 항목입니다.'),
enforcements: Yup.array(Yup.string().oneOf(Object.keys(botEnforcements))),
_csrf: Yup.string().required(),
}
@ -353,7 +349,6 @@ export interface ManageBot {
desc: string
vanity: string
banner: string
enforcements: string[]
bg: string
_csrf: string
}