Compare commits

..

No commits in common. "master" and "v2.9.2" have entirely different histories.

40 changed files with 344 additions and 786 deletions

View File

@ -1,5 +1,4 @@
KOREANBOTS_URL=http://localhost:3000 KOREANBOTS_URL=http://localhost:3000
MYSQL_PORT=3306
MYSQL_HOST=mysql MYSQL_HOST=mysql
MYSQL_USER=root MYSQL_USER=root
MYSQL_PASSWORD=YOUSHALLNOTPASS MYSQL_PASSWORD=YOUSHALLNOTPASS
@ -34,4 +33,3 @@ REVIEW_LOG_WEBHOOK_URL=
OPEN_REVIEW_LOG_WEBHOOK_URL= OPEN_REVIEW_LOG_WEBHOOK_URL=
STATS_LOG_WEBHOOK_URL= STATS_LOG_WEBHOOK_URL=
REPORT_WEBHOOK_URL= REPORT_WEBHOOK_URL=
NOTICE_LOG_WEBHOOK_URL=

View File

@ -18,8 +18,7 @@ const BotCard: React.FC<BotCardProps> = ({ manage = false, bot }) => {
<div <div
className='relative mx-auto h-full rounded-2xl bg-little-white text-black shadow-xl dark:bg-discord-black dark:text-white' className='relative mx-auto h-full rounded-2xl bg-little-white text-black shadow-xl dark:bg-discord-black dark:text-white'
style={ style={
(checkBotFlag(bot.flags, 'trusted') || checkBotFlag(bot.flags, 'partnered')) && checkBotFlag(bot.flags, 'trusted') && bot.banner
bot.banner
? { ? {
background: `linear-gradient(to right, rgba(34, 36, 38, 0.68), rgba(34, 36, 38, 0.68)), url("${bot.banner}") center top / cover no-repeat`, background: `linear-gradient(to right, rgba(34, 36, 38, 0.68), rgba(34, 36, 38, 0.68)), url("${bot.banner}") center top / cover no-repeat`,
color: 'white', color: 'white',

View File

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

View File

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

View File

@ -1,6 +1,5 @@
import { NextSeo } from 'next-seo'
import dynamic from 'next/dynamic' import dynamic from 'next/dynamic'
import { useState } from 'react' import { NextSeo } from 'next-seo'
import { import {
botCategories, botCategories,
@ -14,7 +13,6 @@ const Tag = dynamic(() => import('@components/Tag'))
const Search = dynamic(() => import('@components/Search')) const Search = dynamic(() => import('@components/Search'))
const Hero: React.FC<HeroProps> = ({ type = 'all', header, description }) => { const Hero: React.FC<HeroProps> = ({ type = 'all', header, description }) => {
const [showAllCategories, setShowAllCategories] = useState(false)
const link = `/${type}/categories` const link = `/${type}/categories`
return ( return (
<> <>
@ -29,8 +27,7 @@ const Hero: React.FC<HeroProps> = ({ type = 'all', header, description }) => {
<div className='mb-8 bg-discord-blurple text-gray-100 dark:bg-discord-black md:p-0'> <div className='mb-8 bg-discord-blurple text-gray-100 dark:bg-discord-black md:p-0'>
<Container className='pb-16 pt-24 md:pb-20' ignoreColor> <Container className='pb-16 pt-24 md:pb-20' ignoreColor>
<h1 className='hidden text-left text-3xl font-bold md:block'> <h1 className='hidden text-left text-3xl font-bold md:block'>
{header && `${header} - `} {{ bots: '봇 | ', servers: '서버 | ' }[type] || ''} {header && `${header} - `}
</h1> </h1>
<h1 className='text-center text-3xl font-semibold md:hidden'> <h1 className='text-center text-3xl font-semibold md:hidden'>
{header && ( {header && (
@ -39,7 +36,7 @@ const Hero: React.FC<HeroProps> = ({ type = 'all', header, description }) => {
<br /> <br />
</span> </span>
)} )}
{{ bots: '봇 | ', servers: '서버 | ' }[type] || ''}
</h1> </h1>
<p className='font-base mt-2 text-center text-xl sm:text-left'> <p className='font-base mt-2 text-center text-xl sm:text-left'>
{description || {description ||
@ -112,36 +109,32 @@ const Hero: React.FC<HeroProps> = ({ type = 'all', header, description }) => {
bigger bigger
href={type === 'bots' ? '/bots/list/votes' : '/servers/list/votes'} href={type === 'bots' ? '/bots/list/votes' : '/servers/list/votes'}
/> />
{(type === 'bots' ? botCategories : serverCategories) {(type === 'bots' ? botCategories : serverCategories).slice(0, 4).map((t) => (
.slice(0, showAllCategories ? undefined : 4) <Tag
.map((t) => ( key={t}
<Tag text={
key={t} <>
text={ <i
<> className={(type === 'bots' ? botCategoryIcon : serverCategoryIcon)[t]}
<i />{' '}
className={(type === 'bots' ? botCategoryIcon : serverCategoryIcon)[t]} {t}
/>{' '} </>
{t} }
</> dark
} bigger
dark href={`${link}/${t}`}
bigger />
href={`${link}/${t}`} ))}
/>
))}
<Tag <Tag
key='tag' key='tag'
className='cursor-pointer'
text={ text={
<> <>
<i className='fas fa-tag' />{' '} <i className='fas fa-tag' />
{showAllCategories ? '간략히 보기' : '카테고리 더보기'}
</> </>
} }
dark dark
bigger bigger
onClick={() => setShowAllCategories(!showAllCategories)} href={link}
/> />
</> </>
)} )}

View File

@ -1,16 +1,14 @@
/* eslint-disable jsx-a11y/click-events-have-key-events */ /* eslint-disable jsx-a11y/click-events-have-key-events */
/* eslint-disable jsx-a11y/no-noninteractive-tabindex */ /* eslint-disable jsx-a11y/no-noninteractive-tabindex */
/* eslint-disable jsx-a11y/no-static-element-interactions */ /* eslint-disable jsx-a11y/no-static-element-interactions */
import dynamic from 'next/dynamic'
import Image from 'next/image'
import Link from 'next/link'
import { useRouter } from 'next/router'
import Logo from 'public/logo-transparent.png'
import { useEffect, useState } from 'react' import { useEffect, useState } from 'react'
import Link from 'next/link'
import dynamic from 'next/dynamic'
import { useRouter } from 'next/router'
import { Nullable, User, UserCache } from '@types'
import Fetch from '@utils/Fetch'
import { redirectTo } from '@utils/Tools' import { redirectTo } from '@utils/Tools'
import Fetch from '@utils/Fetch'
import { Nullable, User, UserCache } from '@types'
const DiscordAvatar = dynamic(() => import('@components/DiscordAvatar')) const DiscordAvatar = dynamic(() => import('@components/DiscordAvatar'))
@ -51,16 +49,9 @@ const Navbar: React.FC<NavbarProps> = ({ token }) => {
setUserCache(null) setUserCache(null)
} }
}, [token]) }, [token])
return ( return (
<div className='fixed left-0 right-0 top-0 z-50'> <>
<nav <nav className='fixed top-0 z-40 flex w-full flex-wrap items-center justify-between bg-discord-blurple px-2 py-3 text-gray-100 dark:bg-discord-black lg:absolute'>
className={`fixed top-0 z-40 flex w-full flex-wrap items-center justify-between px-2 py-2 text-gray-100 backdrop-blur-sm transition-colors duration-300 ${
dev
? 'bg-discord-blurple dark:bg-discord-black'
: 'bg-discord-blurple/90 dark:bg-discord-black/30'
} lg:absolute`}
>
<div className='container mx-auto flex flex-wrap items-center justify-between px-4'> <div className='container mx-auto flex flex-wrap items-center justify-between px-4'>
<div className='relative flex w-full justify-between lg:w-auto lg:justify-start'> <div className='relative flex w-full justify-between lg:w-auto lg:justify-start'>
<Link <Link
@ -74,7 +65,7 @@ const Navbar: React.FC<NavbarProps> = ({ token }) => {
<i className='fas fa-tools mr-1' /> DEVELOPERS <i className='fas fa-tools mr-1' /> DEVELOPERS
</> </>
) : ( ) : (
<Image src={Logo} alt='Koreanbots' width={100} height={100} className='h-10 w-10' /> 'KOREANLIST'
)} )}
</Link> </Link>
<button <button
@ -169,7 +160,7 @@ const Navbar: React.FC<NavbarProps> = ({ token }) => {
</li> </li>
</ul> </ul>
</div> </div>
<div className='hidden lg:flex lg:items-center lg:bg-transparent lg:shadow-none'> <div className='hidden grow items-center bg-white lg:flex lg:bg-transparent lg:shadow-none'>
<ul className='flex list-none flex-col lg:ml-auto lg:flex-row'> <ul className='flex list-none flex-col lg:ml-auto lg:flex-row'>
<li <li
className='flex items-center outline-none' className='flex items-center outline-none'
@ -377,7 +368,7 @@ const Navbar: React.FC<NavbarProps> = ({ token }) => {
)} )}
</div> </div>
</div> </div>
</div> </>
) )
} }

View File

@ -1,10 +1,10 @@
import { Bot, ResponseProps, Server } from '@types'
import Fetch from '@utils/Fetch'
import { makeBotURL, makeServerURL, redirectTo } from '@utils/Tools'
import dynamic from 'next/dynamic'
import Link from 'next/link'
import { useRouter } from 'next/router'
import { useEffect, useRef, useState } from 'react' import { useEffect, useRef, useState } from 'react'
import { useRouter } from 'next/router'
import Link from 'next/link'
import dynamic from 'next/dynamic'
import { makeBotURL, makeServerURL, redirectTo } from '@utils/Tools'
import Fetch from '@utils/Fetch'
import { Bot, Server, ResponseProps } from '@types'
import Day from '@utils/Day' import Day from '@utils/Day'
import useOutsideClick from '@utils/useOutsideClick' import useOutsideClick from '@utils/useOutsideClick'
@ -12,11 +12,7 @@ import useOutsideClick from '@utils/useOutsideClick'
const DiscordAvatar = dynamic(() => import('@components/DiscordAvatar')) const DiscordAvatar = dynamic(() => import('@components/DiscordAvatar'))
const ServerIcon = dynamic(() => import('@components/ServerIcon')) const ServerIcon = dynamic(() => import('@components/ServerIcon'))
interface SearchProps { const Search: React.FC = () => {
compact?: boolean
}
const Search: React.FC<SearchProps> = ({ compact = false }) => {
const router = useRouter() const router = useRouter()
const ref = useRef() const ref = useRef()
const [query, setQuery] = useState('') const [query, setQuery] = useState('')
@ -105,13 +101,12 @@ const Search: React.FC<SearchProps> = ({ compact = false }) => {
} }
return ( return (
<div className={`relative w-full z-10 ${compact ? '' : 'mt-5'}`}> <div onFocus={() => setHidden(false)} ref={ref}>
<div onFocus={() => setHidden(false)} ref={ref}> <div className='relative z-10 mt-5 flex w-full rounded-lg bg-white text-black dark:bg-very-black dark:text-gray-100'>
<div className={`relative z-10 flex w-full items-center bg-white text-black dark:bg-very-black dark:text-gray-100 ${compact ? 'h-10 px-3 rounded-md' : 'rounded-lg'}`}>
<input <input
type='search' type='search'
maxLength={50} maxLength={50}
className={`grow border-0 border-none bg-transparent pr-20 shadow outline-none ${compact ? 'h-10 text-sm' : 'h-16 px-7 py-3 text-xl'}`} className='h-16 grow border-0 border-none bg-transparent px-7 py-3 pr-20 text-xl shadow outline-none'
placeholder='검색...' placeholder='검색...'
value={query} value={query}
onChange={(e) => { onChange={(e) => {
@ -124,14 +119,14 @@ const Search: React.FC<SearchProps> = ({ compact = false }) => {
}} }}
/> />
<button <button
className='absolute right-4 top-1/2 -translate-y-1/2 outline-none' className='cusor-pointer absolute right-0 top-0 mr-5 mt-5 outline-none'
onClick={onSubmit} onClick={onSubmit}
> >
<i className={`fas fa-search text-gray-600 hover:text-gray-700 ${compact ? 'text-sm' : 'text-2xl'}`} /> <i className='fas fa-search text-2xl text-gray-600 hover:text-gray-700' />
</button> </button>
</div> </div>
<div className={`relative ${hidden ? 'hidden' : 'block'} z-50`}> <div className={`relative ${hidden ? 'hidden' : 'block'} z-50`}>
<div className='absolute top-full mt-2 max-h-60 w-full overflow-y-auto rounded bg-white text-black shadow-md dark:bg-very-black dark:text-gray-100 md:h-80'> <div className='pin-t pin-l absolute my-2 h-60 w-full overflow-y-scroll rounded bg-white text-black shadow-md dark:bg-very-black dark:text-gray-100 md:h-80'>
<ul> <ul>
{data && data.code === 200 ? ( {data && data.code === 200 ? (
<div className='grid lg:grid-cols-2'> <div className='grid lg:grid-cols-2'>
@ -177,7 +172,7 @@ const Search: React.FC<SearchProps> = ({ compact = false }) => {
<li className='px-3 py-3.5'>...</li> <li className='px-3 py-3.5'>...</li>
</ul> </ul>
) : ( ) : (
<ul className='px-3 py-3.5'> <ul>
{query && data ? ( {query && data ? (
data.message?.includes('문법') ? ( data.message?.includes('문법') ? (
<li className='px-3 py-3.5'> <li className='px-3 py-3.5'>
@ -199,10 +194,10 @@ const Search: React.FC<SearchProps> = ({ compact = false }) => {
) )
) : query.length === 0 ? ( ) : query.length === 0 ? (
!recentSearch || !Array.isArray(recentSearch) || recentSearch.length === 0 ? ( !recentSearch || !Array.isArray(recentSearch) || recentSearch.length === 0 ? (
<li > .</li> <li className='px-3 py-3.5'> .</li>
) : ( ) : (
<> <>
<li className='h-15 cursor-pointer font-semibold'> <li className='h-15 cursor-pointer px-3 py-2 font-semibold'>
<button <button
className='absolute right-0 pr-10 text-sm text-red-500 hover:opacity-90' className='absolute right-0 pr-10 text-sm text-red-500 hover:opacity-90'
@ -241,7 +236,6 @@ const Search: React.FC<SearchProps> = ({ compact = false }) => {
</div> </div>
</div> </div>
</div> </div>
</div>
) )
} }

View File

@ -27,9 +27,7 @@ const ServerCard: React.FC<BotCardProps> = ({ type, server }) => {
<div <div
className='relative mx-auto h-full rounded-2xl bg-little-white text-black shadow-xl dark:bg-discord-black dark:text-white' className='relative mx-auto h-full rounded-2xl bg-little-white text-black shadow-xl dark:bg-discord-black dark:text-white'
style={ style={
(checkServerFlag(server.flags, 'trusted') || checkServerFlag(server.flags, 'trusted') && server.banner
checkServerFlag(server.flags, 'partnered')) &&
server.banner
? { ? {
background: `linear-gradient(to right, rgba(34, 36, 38, 0.68), rgba(34, 36, 38, 0.68)), url("${server.banner}") center top / cover no-repeat`, background: `linear-gradient(to right, rgba(34, 36, 38, 0.68), rgba(34, 36, 38, 0.68)), url("${server.banner}") center top / cover no-repeat`,
color: 'white', color: 'white',

View File

@ -7,6 +7,5 @@ export async function register() {
version: packageJson.version, version: packageJson.version,
env: process.env.DD_ENV, env: process.env.DD_ENV,
}) })
tracer.use('next')
} }
} }

View File

@ -1,6 +1,6 @@
{ {
"name": "koreanbots", "name": "koreanbots",
"version": "2.12.2", "version": "2.9.2",
"private": true, "private": true,
"scripts": { "scripts": {
"dev": "next dev", "dev": "next dev",
@ -28,10 +28,11 @@
"csrf": "3.1.0", "csrf": "3.1.0",
"dataloader": "2.2.2", "dataloader": "2.2.2",
"dayjs": "^1.11.9", "dayjs": "^1.11.9",
"dd-trace": "5.24.0", "dd-trace": "^5.30.0",
"difflib": "0.2.4", "difflib": "0.2.4",
"discord.js": "^14.12.1", "discord.js": "^14.12.1",
"emoji-mart": "3.0.1", "emoji-mart": "3.0.1",
"erlpack": "0.1.4",
"express-rate-limit": "^5.3.0", "express-rate-limit": "^5.3.0",
"firebase": "^11.2.0", "firebase": "^11.2.0",
"firebase-admin": "^13.0.2", "firebase-admin": "^13.0.2",
@ -40,9 +41,9 @@
"josa": "3.0.1", "josa": "3.0.1",
"jsonwebtoken": "^9.0.0", "jsonwebtoken": "^9.0.0",
"knex": "^2.4.0", "knex": "^2.4.0",
"mongoose": "6.13.6", "mongoose": "6.13.5",
"mysql": "2.18.1", "mysql": "2.18.1",
"next": "^14.2.32", "next": "^14.2.22",
"next-connect": "0.10.1", "next-connect": "0.10.1",
"next-pwa": "^5.6.0", "next-pwa": "^5.6.0",
"next-seo": "^6.1.0", "next-seo": "^6.1.0",
@ -100,6 +101,5 @@
"resolutions": { "resolutions": {
"@types/react": "^17.0.15" "@types/react": "^17.0.15"
}, },
"license": "AGPL-3.0", "license": "AGPL-3.0"
"packageManager": "yarn@1.22.22+sha512.a6b2f7906b721bba3d67d4aff083df04dad64c399707841b7acf00f6b133b7ac24255f2652fa22ae3534329dc6180534e98d17432037ff6fd140556e2bb3137e"
} }

View File

@ -1,28 +1,28 @@
import { DefaultSeo } from 'next-seo' import Head from 'next/head'
import App, { AppContext, AppProps } from 'next/app' import App, { AppContext, AppProps } from 'next/app'
import dynamic from 'next/dynamic' import dynamic from 'next/dynamic'
import Head from 'next/head'
import { Router, useRouter } from 'next/router' import { Router, useRouter } from 'next/router'
import NProgress from 'nprogress'
import { useEffect, useState } from 'react' import { useEffect, useState } from 'react'
import ReactGA from 'react-ga' import { DefaultSeo } from 'next-seo'
import { GlobalHotKeys } from 'react-hotkeys' import { GlobalHotKeys } from 'react-hotkeys'
import NProgress from 'nprogress'
import Package from '../package.json' import Package from '../package.json'
import ReactGA from 'react-ga'
import { Theme } from '@types'
import { DESCRIPTION, shortcutKeyMap, THEME_COLOR, TITLE } from '@utils/Constants'
import Logger from '@utils/Logger' import Logger from '@utils/Logger'
import { handlePWA, parseCookie, parseDockerhubTag, 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'
const Footer = dynamic(() => import('@components/Footer')) const Footer = dynamic(() => import('@components/Footer'))
const Navbar = dynamic(() => import('@components/Navbar')) const Navbar = dynamic(() => import('@components/Navbar'))
const Modal = dynamic(() => import('@components/Modal')) const Modal = dynamic(() => import('@components/Modal'))
import PlatformDisplay from '@components/PlatformDisplay'
import '@fortawesome/fontawesome-free/css/all.css'
import 'rc-tooltip/assets/bootstrap_white.css'
import '../app.css' import '../app.css'
import '../github-markdown.css' import '../github-markdown.css'
import 'rc-tooltip/assets/bootstrap_white.css'
import '@fortawesome/fontawesome-free/css/all.css'
import PlatformDisplay from '@components/PlatformDisplay'
// Progress Bar // Progress Bar
NProgress.configure({ showSpinner: false }) NProgress.configure({ showSpinner: false })

View File

@ -10,7 +10,7 @@ import HCaptcha from '@hcaptcha/react-hcaptcha'
import { get } from '@utils/Query' import { get } from '@utils/Query'
import { cleanObject, parseCookie, redirectTo } from '@utils/Tools' import { cleanObject, parseCookie, redirectTo } from '@utils/Tools'
import { AddBotSubmit, AddBotSubmitSchema } from '@utils/Yup' 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 { getToken } from '@utils/Csrf'
import Fetch from '@utils/Fetch' import Fetch from '@utils/Fetch'
import { ResponseProps, SubmittedBot, Theme, User } from '@types' import { ResponseProps, SubmittedBot, Theme, User } from '@types'
@ -57,7 +57,6 @@ const AddBot: NextPage<AddBotProps> = ({ logged, user, csrfToken, theme }) => {
- -
- -
- ?`, - ?`,
enforcements: [],
_csrf: csrfToken, _csrf: csrfToken,
_captcha: 'captcha', _captcha: 'captcha',
} }
@ -176,18 +175,6 @@ const AddBot: NextPage<AddBotProps> = ({ logged, user, csrfToken, theme }) => {
. .
</li> </li>
<li>, API에 .</li> <li>, API에 .</li>
<li>
{' '}
<Link
href='https://contents.koreanbots.dev/bot-review'
rel='noreferrer'
target='_blank'
className='text-blue-500 hover:text-blue-600'
>
</Link>
.
</li>
</ul> </ul>
</Message> </Message>
</div> </div>
@ -199,8 +186,8 @@ const AddBot: NextPage<AddBotProps> = ({ logged, user, csrfToken, theme }) => {
<div className='flex items-center'> <div className='flex items-center'>
<CheckBox name='agree' /> <CheckBox name='agree' />
<strong className='ml-2 text-sm'> <strong className='ml-2 text-sm'>
, ,
. .
</strong> </strong>
</div> </div>
</Label> </Label>
@ -369,44 +356,6 @@ const AddBot: NextPage<AddBotProps> = ({ logged, user, csrfToken, theme }) => {
</Segment> </Segment>
</Label> </Label>
<Divider /> <Divider />
<Label
For='enforcements'
label='필수 고지 내용'
labelDesc='내용에 해당하는 경우 필수로 선택해야 합니다.'
required
error={
errors.enforcements && touched.enforcements ? (errors.enforcements as string) : null
}
>
<Selects
options={Object.entries(botEnforcements)
.filter(([k]) => k === 'NONE' || !values.enforcements.includes('NONE'))
.map(([k, v]) => ({
label: v.label,
value: k,
}))}
handleChange={(values) => {
if (values.some((i) => i.value === 'NONE')) {
setFieldValue('enforcements', ['NONE'])
} else {
setFieldValue(
'enforcements',
values.map((v) => v.value)
)
}
}}
handleTouch={() => setFieldTouched('enforcements', true)}
values={values.enforcements ?? ([] as string[])}
setValues={(values) => {
if (values.includes('NONE')) {
setFieldValue('enforcements', ['NONE'])
} else {
setFieldValue('enforcements', values)
}
}}
/>
</Label>
<Divider />
<p className='mb-5 mt-2 text-base'> <p className='mb-5 mt-2 text-base'>
<span className='font-semibold text-red-500'> *</span> = <span className='font-semibold text-red-500'> *</span> =
</p> </p>

View File

@ -10,13 +10,12 @@ import {
AddBotSubmit, AddBotSubmit,
AddBotSubmitSchema, AddBotSubmitSchema,
CsrfCaptcha, CsrfCaptcha,
getManageBotSchema,
ManageBot, ManageBot,
ManageBotSchema,
} from '@utils/Yup' } from '@utils/Yup'
import RequestHandler from '@utils/RequestHandler' import RequestHandler from '@utils/RequestHandler'
import { User } from '@types' import { User } from '@types'
import { import {
checkBotFlag,
checkUserFlag, checkUserFlag,
diff, diff,
inspect, inspect,
@ -26,6 +25,7 @@ import {
} from '@utils/Tools' } from '@utils/Tools'
import { discordLog, getMainGuild, webhookClients } from '@utils/DiscordBot' import { discordLog, getMainGuild, webhookClients } from '@utils/DiscordBot'
import { KoreanbotsEndPoints } from '@utils/Constants' import { KoreanbotsEndPoints } from '@utils/Constants'
import { userInfo } from 'os'
const patchLimiter = rateLimit({ const patchLimiter = rateLimit({
windowMs: 2 * 60 * 1000, windowMs: 2 * 60 * 1000,
@ -39,10 +39,6 @@ const patchLimiter = rateLimit({
}) })
const Bots = RequestHandler() const Bots = RequestHandler()
.get(async (req: GetApiRequest, res) => { .get(async (req: GetApiRequest, res) => {
const auth = req.headers.authorization
? await get.BotAuthorization(req.headers.authorization)
: await get.Authorization(req.cookies.token)
if (!auth) return ResponseWrapper(res, { code: 401 })
const bot = await get.bot.load(req.query.id) const bot = await get.bot.load(req.query.id)
if (!bot) return ResponseWrapper(res, { code: 404, message: '존재하지 않는 봇입니다.' }) if (!bot) return ResponseWrapper(res, { code: 404, message: '존재하지 않는 봇입니다.' })
else { else {
@ -132,11 +128,7 @@ const Bots = RequestHandler()
: `${userinfo.username}#${userinfo.tag}`, : `${userinfo.username}#${userinfo.tag}`,
iconURL: iconURL:
KoreanbotsEndPoints.URL.root + KoreanbotsEndPoints.URL.root +
KoreanbotsEndPoints.CDN.avatar(userinfo.id, { KoreanbotsEndPoints.CDN.avatar(userinfo.id, { format: 'png', size: 256, hash: userinfo.avatar }),
format: 'png',
size: 256,
hash: userinfo.avatar,
}),
url: KoreanbotsEndPoints.URL.user(userinfo.id), url: KoreanbotsEndPoints.URL.user(userinfo.id),
}) })
.setTitle('대기 중') .setTitle('대기 중')
@ -201,10 +193,6 @@ const Bots = RequestHandler()
if (!bot) return ResponseWrapper(res, { code: 404, message: '존재하지 않는 봇입니다.' }) if (!bot) return ResponseWrapper(res, { code: 404, message: '존재하지 않는 봇입니다.' })
const user = await get.Authorization(req.cookies.token) const user = await get.Authorization(req.cookies.token)
if (!user) return ResponseWrapper(res, { code: 401 }) if (!user) return ResponseWrapper(res, { code: 401 })
const isPerkAvailable =
checkBotFlag(bot.flags, 'partnered') || checkBotFlag(bot.flags, 'trusted')
const userInfo = await get.user.load(user) const userInfo = await get.user.load(user)
if ( if (
['reported', 'blocked', 'archived'].includes(bot.state) && ['reported', 'blocked', 'archived'].includes(bot.state) &&
@ -223,8 +211,7 @@ const Bots = RequestHandler()
const csrfValidated = checkToken(req, res, req.body._csrf) const csrfValidated = checkToken(req, res, req.body._csrf)
if (!csrfValidated) return if (!csrfValidated) return
const validated: ManageBot = await getManageBotSchema(isPerkAvailable) const validated = await ManageBotSchema.validate(req.body, { abortEarly: false })
.validate(req.body, { abortEarly: false })
.then((el) => el) .then((el) => el)
.catch((e) => { .catch((e) => {
ResponseWrapper(res, { code: 400, errors: e.errors }) ResponseWrapper(res, { code: 400, errors: e.errors })
@ -232,49 +219,11 @@ const Bots = RequestHandler()
}) })
if (!validated) return if (!validated) return
if (!isPerkAvailable && (validated.vanity || validated.banner || validated.bg))
return ResponseWrapper(res, {
code: 403,
message: '해당 봇은 특전을 이용할 권한이 없습니다.',
})
if (validated.vanity) {
const vanity = await get.bot.load(validated.vanity)
if (vanity && vanity.id !== bot.id) {
return ResponseWrapper(res, {
code: 403,
message: '이미 사용중인 한디리 커스텀 URL 입니다.',
errors: ['다른 커스텀 URL로 다시 시도해주세요.'],
})
}
if (validated.vanity !== bot.vanity) {
await webhookClients.internal.noticeLog.send({
embeds: [
{
title: '한디리 커스텀 URL 변경',
description: `봇: ${bot.name} - <@${bot.id}> ([${
bot.id
}](${KoreanbotsEndPoints.URL.bot(bot.id)}))`,
fields: [
{
name: '이전',
value: bot.vanity || '없음',
},
{
name: '이후',
value: validated.vanity || '없음',
},
],
color: Colors.Blue,
},
],
})
}
}
const result = await update.bot(req.query.id, validated) const result = await update.bot(req.query.id, validated)
if (result === 0) return ResponseWrapper(res, { code: 400 }) if (result === 0) return ResponseWrapper(res, { code: 400 })
else { else {
get.bot.clear(req.query.id) get.bot.clear(req.query.id)
get.bot.clear(bot.vanity)
const embed = new EmbedBuilder().setDescription( const embed = new EmbedBuilder().setDescription(
`${bot.name} - <@${bot.id}> ([${bot.id}](${KoreanbotsEndPoints.URL.bot(bot.id)}))` `${bot.name} - <@${bot.id}> ([${bot.id}](${KoreanbotsEndPoints.URL.bot(bot.id)}))`
) )
@ -288,10 +237,6 @@ const Bots = RequestHandler()
discord: bot.discord, discord: bot.discord,
intro: bot.intro, intro: bot.intro,
category: JSON.stringify(bot.category), category: JSON.stringify(bot.category),
vanity: bot.vanity,
banner: bot.banner,
enforcements: JSON.stringify(bot.enforcements),
bg: bot.bg,
}, },
{ {
prefix: validated.prefix, prefix: validated.prefix,
@ -302,10 +247,6 @@ const Bots = RequestHandler()
discord: validated.discord, discord: validated.discord,
intro: validated.intro, intro: validated.intro,
category: JSON.stringify(validated.category), category: JSON.stringify(validated.category),
vanity: validated.vanity,
banner: validated.banner,
enforcements: JSON.stringify(validated.enforcements),
bg: validated.bg,
} }
) )
diffData.forEach((d) => { diffData.forEach((d) => {

View File

@ -4,11 +4,7 @@ import ResponseWrapper from '@utils/ResponseWrapper'
import { Bot, List } from '@types' import { Bot, List } from '@types'
const NewList = RequestHandler().get(async (req, res) => { const NewList = RequestHandler().get(async (_req, res) => {
const auth = req.headers.authorization
? await get.BotAuthorization(req.headers.authorization)
: await get.Authorization(req.cookies.token)
if (!auth) return ResponseWrapper(res, { code: 401 })
const result = await get.list.new.load(1) const result = await get.list.new.load(1)
return ResponseWrapper<List<Bot>>(res, { code: 200, data: result }) return ResponseWrapper<List<Bot>>(res, { code: 200, data: result })
}) })

View File

@ -6,10 +6,6 @@ import { Bot, List } from '@types'
import Yup from '@utils/Yup' import Yup from '@utils/Yup'
const VotesList = RequestHandler().get(async (req, res) => { const VotesList = RequestHandler().get(async (req, res) => {
const auth = req.headers.authorization
? await get.BotAuthorization(req.headers.authorization)
: await get.Authorization(req.cookies.token)
if (!auth) return ResponseWrapper(res, { code: 401 })
const page = await Yup.number() const page = await Yup.number()
.positive() .positive()
.integer() .integer()

View File

@ -8,10 +8,6 @@ import { SearchQuerySchema } from '@utils/Yup'
import { Bot, Server, List } from '@types' import { Bot, Server, List } from '@types'
const Search = RequestHandler().get(async (req: ApiRequest, res) => { const Search = RequestHandler().get(async (req: ApiRequest, res) => {
const auth = req.headers.authorization
? await get.BotAuthorization(req.headers.authorization)
: await get.Authorization(req.cookies.token)
if (!auth) return ResponseWrapper(res, { code: 401 })
const validated = await SearchQuerySchema.validate({ q: req.query.q || req.query.query, page: 1 }) const validated = await SearchQuerySchema.validate({ q: req.query.q || req.query.query, page: 1 })
.then((el) => el) .then((el) => el)
.catch((e) => { .catch((e) => {

View File

@ -8,10 +8,6 @@ import { SearchQuerySchema } from '@utils/Yup'
import { Bot, List } from '@types' import { Bot, List } from '@types'
const SearchBots = RequestHandler().get(async (req: ApiRequest, res: NextApiResponse) => { const SearchBots = RequestHandler().get(async (req: ApiRequest, res: NextApiResponse) => {
const auth = req.headers.authorization
? await get.BotAuthorization(req.headers.authorization)
: await get.Authorization(req.cookies.token)
if (!auth) return ResponseWrapper(res, { code: 401 })
const validated = await SearchQuerySchema.validate({ const validated = await SearchQuerySchema.validate({
q: req.query.q || req.query.query, q: req.query.q || req.query.query,
page: req.query.page, page: req.query.page,

View File

@ -8,10 +8,6 @@ import { SearchQuerySchema } from '@utils/Yup'
import { Server, List } from '@types' import { Server, List } from '@types'
const SearchServers = RequestHandler().get(async (req: ApiRequest, res: NextApiResponse) => { const SearchServers = RequestHandler().get(async (req: ApiRequest, res: NextApiResponse) => {
const auth = req.headers.authorization
? await get.BotAuthorization(req.headers.authorization)
: await get.Authorization(req.cookies.token)
if (!auth) return ResponseWrapper(res, { code: 401 })
const validated = await SearchQuerySchema.validate({ const validated = await SearchQuerySchema.validate({
q: req.query.q || req.query.query, q: req.query.q || req.query.query,
page: req.query.page, page: req.query.page,

View File

@ -36,10 +36,6 @@ const patchLimiter = rateLimit({
}) })
const Servers = RequestHandler() const Servers = RequestHandler()
.get(async (req: GetApiRequest, res) => { .get(async (req: GetApiRequest, res) => {
const auth = req.headers.authorization
? await get.BotAuthorization(req.headers.authorization)
: await get.Authorization(req.cookies.token)
if (!auth) return ResponseWrapper(res, { code: 401 })
const server = await get.server.load(req.query.id) const server = await get.server.load(req.query.id)
if (!server) return ResponseWrapper(res, { code: 404, message: '존재하지 않는 서버 입니다.' }) if (!server) return ResponseWrapper(res, { code: 404, message: '존재하지 않는 서버 입니다.' })
else { else {

View File

@ -5,10 +5,7 @@ import ResponseWrapper from '@utils/ResponseWrapper'
import RequestHandler from '@utils/RequestHandler' import RequestHandler from '@utils/RequestHandler'
const Users = RequestHandler().get(async (req: ApiRequest, res) => { const Users = RequestHandler().get(async (req: ApiRequest, res) => {
const auth = req.headers.authorization console.log(req.query)
? await get.BotAuthorization(req.headers.authorization)
: await get.Authorization(req.cookies.token)
if (!auth) return ResponseWrapper(res, { code: 401 })
const user = await get.user.load(req.query?.id) const user = await get.user.load(req.query?.id)
if (!user) return ResponseWrapper(res, { code: 404, message: '존재하지 않는 유저 입니다.' }) if (!user) return ResponseWrapper(res, { code: 404, message: '존재하지 않는 유저 입니다.' })
else return ResponseWrapper(res, { code: 200, data: user }) else return ResponseWrapper(res, { code: 200, data: user })

View File

@ -9,16 +9,9 @@ import { ParsedUrlQuery } from 'querystring'
import { getJosaPicker } from 'josa' import { getJosaPicker } from 'josa'
import { get } from '@utils/Query' import { get } from '@utils/Query'
import { import { checkUserFlag, cleanObject, makeBotURL, parseCookie, redirectTo } from '@utils/Tools'
checkBotFlag, import { ManageBot, ManageBotSchema } from '@utils/Yup'
checkUserFlag, import { botCategories, botCategoryDescription, library } from '@utils/Constants'
cleanObject,
makeBotURL,
parseCookie,
redirectTo,
} from '@utils/Tools'
import { ManageBot, getManageBotSchema } from '@utils/Yup'
import { botCategories, botCategoryDescription, botEnforcements, library } from '@utils/Constants'
import { Bot, Theme, User } from '@types' import { Bot, Theme, User } from '@types'
import { getToken } from '@utils/Csrf' import { getToken } from '@utils/Csrf'
import Fetch from '@utils/Fetch' import Fetch from '@utils/Fetch'
@ -65,7 +58,7 @@ const ManageBotPage: NextPage<ManageBotProps> = ({ bot, user, csrfToken, theme }
else return null else return null
} }
if (!bot?.id) return <NotFound /> if (!bot) return <NotFound />
if (!user) if (!user)
return ( return (
<Login> <Login>
@ -77,7 +70,6 @@ const ManageBotPage: NextPage<ManageBotProps> = ({ bot, user, csrfToken, theme }
!checkUserFlag(user.flags, 'staff') !checkUserFlag(user.flags, 'staff')
) )
return <Forbidden /> return <Forbidden />
const isPerkAvailable = checkBotFlag(bot.flags, 'trusted') || checkBotFlag(bot.flags, 'partnered')
return ( return (
<Container paddingTop className='pb-10 pt-5'> <Container paddingTop className='pb-10 pt-5'>
<NextSeo title={`${bot.name} 수정하기`} description='봇의 정보를 수정합니다.' /> <NextSeo title={`${bot.name} 수정하기`} description='봇의 정보를 수정합니다.' />
@ -89,29 +81,21 @@ const ManageBotPage: NextPage<ManageBotProps> = ({ bot, user, csrfToken, theme }
prefix: bot.prefix, prefix: bot.prefix,
library: bot.lib, library: bot.lib,
category: bot.category, category: bot.category,
enforcements: bot.enforcements,
intro: bot.intro, intro: bot.intro,
desc: bot.desc, desc: bot.desc,
website: bot.web, website: bot.web,
url: bot.url, url: bot.url,
git: bot.git, git: bot.git,
discord: bot.discord, discord: bot.discord,
vanity: isPerkAvailable && bot.vanity,
banner: isPerkAvailable && bot.banner,
bg: isPerkAvailable && bot.bg,
_csrf: csrfToken, _csrf: csrfToken,
})} })}
validationSchema={getManageBotSchema(isPerkAvailable)} validationSchema={ManageBotSchema}
onSubmit={submitBot} onSubmit={submitBot}
> >
{({ errors, touched, values, setFieldTouched, setFieldValue }) => ( {({ errors, touched, values, setFieldTouched, setFieldValue }) => (
<Form> <Form>
<div className='text-ceznter md:flex md:text-left'> <div className='text-center md:flex md:text-left'>
<DiscordAvatar <DiscordAvatar userID={bot.id} className='mx-auto rounded-full md:mx-1' hash={bot.avatar}/>
userID={bot.id}
className='mx-auto rounded-full md:mx-1'
hash={bot.avatar}
/>
<div className='px-8 py-6 md:w-2/3'> <div className='px-8 py-6 md:w-2/3'>
<h1 className='text-3xl font-bold'> <h1 className='text-3xl font-bold'>
{bot.name}#{bot.tag} {bot.name}#{bot.tag}
@ -177,11 +161,7 @@ const ManageBotPage: NextPage<ManageBotProps> = ({ bot, user, csrfToken, theme }
error={errors.category && touched.category ? (errors.category as string) : null} error={errors.category && touched.category ? (errors.category as string) : null}
> >
<Selects <Selects
options={botCategories.map((el) => ({ options={botCategories.map((el) => ({ label: el, value: el, description: botCategoryDescription[el] }))}
label: el,
value: el,
description: botCategoryDescription[el],
}))}
handleChange={(value) => { handleChange={(value) => {
setFieldValue( setFieldValue(
'category', 'category',
@ -289,83 +269,6 @@ const ManageBotPage: NextPage<ManageBotProps> = ({ bot, user, csrfToken, theme }
<Markdown text={values.desc} /> <Markdown text={values.desc} />
</Segment> </Segment>
</Label> </Label>
{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>
<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'
label='배너 URL'
labelDesc='봇 목록의 카드에 표시되는 이미지입니다.'
error={errors.banner && touched.banner ? errors.banner : null}
>
<Input name='banner' placeholder='https://koreanbots.dev/logo.png' />
</Label>
<Label
For='bg'
label='배경 URL'
labelDesc='봇 페이지 배경에 표시되는 이미지입니다.'
error={errors.bg && touched.bg ? errors.bg : null}
>
<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)
.filter(([k]) => k === 'NONE' || !values.enforcements.includes('NONE'))
.map(([k, v]) => ({
label: v.label,
value: k,
}))}
handleChange={(values) => {
if (values.some((i) => i.value === 'NONE')) {
setFieldValue('enforcements', ['NONE'])
} else {
setFieldValue(
'enforcements',
values.map((v) => v.value)
)
}
}}
handleTouch={() => setFieldTouched('enforcements', true)}
values={values.enforcements ?? ([] as string[])}
setValues={(values) => {
if (values.includes('NONE')) {
setFieldValue('enforcements', ['NONE'])
} else {
setFieldValue('enforcements', values)
}
}}
/>
</Label>
<Divider /> <Divider />
<p className='mb-5 mt-2 text-base'> <p className='mb-5 mt-2 text-base'>
<span className='font-semibold text-red-500'> *</span> = <span className='font-semibold text-red-500'> *</span> =
@ -671,11 +574,9 @@ const ManageBotPage: NextPage<ManageBotProps> = ({ bot, user, csrfToken, theme }
export const getServerSideProps = async (ctx: Context) => { export const getServerSideProps = async (ctx: Context) => {
const parsed = parseCookie(ctx.req) const parsed = parseCookie(ctx.req)
const user = await get.Authorization(parsed?.token) const user = await get.Authorization(parsed?.token)
const bot = await get.bot.load(ctx.query.id)
const spec = await get.botSpec(bot?.id || '', user || '')
return { return {
props: { props: {
bot: { ...bot, banner: spec?.banner || null, bg: spec?.bg || null }, bot: await get.bot.load(ctx.query.id),
user: await get.user.load(user || ''), user: await get.user.load(user || ''),
csrfToken: getToken(ctx.req, ctx.res), csrfToken: getToken(ctx.req, ctx.res),
}, },

View File

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

View File

@ -1,7 +1,7 @@
import { Field, Form, Formik } from 'formik'
import { NextPage } from 'next' import { NextPage } from 'next'
import dynamic from 'next/dynamic'
import Link from 'next/link' import Link from 'next/link'
import dynamic from 'next/dynamic'
import { Field, Form, Formik } from 'formik'
import { Bot, CsrfContext, ResponseProps, User } from '@types' import { Bot, CsrfContext, ResponseProps, User } from '@types'
import { get } from '@utils/Query' import { get } from '@utils/Query'
@ -9,15 +9,15 @@ import { makeBotURL, parseCookie } from '@utils/Tools'
import { ParsedUrlQuery } from 'querystring' import { ParsedUrlQuery } from 'querystring'
import { DMCA, TextField } from '@components/ReportTemplate' import NotFound from 'pages/404'
import { reportCats } from '@utils/Constants'
import { getToken } from '@utils/Csrf' import { getToken } from '@utils/Csrf'
import { DMCA, TextField } from '@components/ReportTemplate'
import { useState } from 'react'
import Fetch from '@utils/Fetch' import Fetch from '@utils/Fetch'
import { ReportSchema } from '@utils/Yup' import { ReportSchema } from '@utils/Yup'
import { getJosaPicker } from 'josa' import { getJosaPicker } from 'josa'
import { reportCats } from '@utils/Constants'
import { NextSeo } from 'next-seo' import { NextSeo } from 'next-seo'
import NotFound from 'pages/404'
import { useState } from 'react'
const Container = dynamic(() => import('@components/Container')) const Container = dynamic(() => import('@components/Container'))
const Message = dynamic(() => import('@components/Message')) const Message = dynamic(() => import('@components/Message'))
@ -37,7 +37,7 @@ const ReportBot: NextPage<ReportBotProps> = ({ data, user, csrfToken }) => {
<NextSeo title={`${data.name} 신고하기`} /> <NextSeo title={`${data.name} 신고하기`} />
<Link href={makeBotURL(data)} className='text-blue-500 hover:opacity-80'> <Link href={makeBotURL(data)} className='text-blue-500 hover:opacity-80'>
<i className='fas fa-arrow-left mb-3 mt-3' /> <strong>{data.name}</strong> <i className='fas fa-arrow-left mb-3 mt-3' /> <strong>{data.name}</strong>
{getJosaPicker('로')(data.name)} {getJosaPicker('로')(data.name)}
</Link> </Link>
{reportRes?.code === 200 ? ( {reportRes?.code === 200 ? (
<Message type='success'> <Message type='success'>

View File

@ -1,24 +1,24 @@
import { NextPage } from 'next' import { NextPage } from 'next'
import dynamic from 'next/dynamic'
import Link from 'next/link' import Link from 'next/link'
import dynamic from 'next/dynamic'
import { useRouter } from 'next/router' import { useRouter } from 'next/router'
import { Bot, CsrfContext, ResponseProps, Theme, User } from '@types' import { Bot, CsrfContext, ResponseProps, Theme, User } from '@types'
import { get } from '@utils/Query' import { get } from '@utils/Query'
import { checkBotFlag, makeBotURL, parseCookie } from '@utils/Tools' import { makeBotURL, parseCookie, checkBotFlag } from '@utils/Tools'
import { ParsedUrlQuery } from 'querystring' import { ParsedUrlQuery } from 'querystring'
import Captcha from '@components/Captcha'
import SetNotification, { getFCMToken } from '@components/FCM'
import { KoreanbotsEndPoints } from '@utils/Constants'
import { getToken } from '@utils/Csrf'
import Day from '@utils/Day'
import Fetch from '@utils/Fetch'
import { getJosaPicker } from 'josa'
import { NextSeo } from 'next-seo'
import NotFound from 'pages/404' import NotFound from 'pages/404'
import { getToken } from '@utils/Csrf'
import Captcha from '@components/Captcha'
import { useEffect, useRef, useState } from 'react' import { useEffect, useRef, useState } from 'react'
import Fetch from '@utils/Fetch'
import Day from '@utils/Day'
import { getJosaPicker } from 'josa'
import { KoreanbotsEndPoints } from '@utils/Constants'
import { NextSeo } from 'next-seo'
import SetNotification, { getFCMToken } from '@components/FCM'
const Container = dynamic(() => import('@components/Container')) const Container = dynamic(() => import('@components/Container'))
const DiscordAvatar = dynamic(() => import('@components/DiscordAvatar')) const DiscordAvatar = dynamic(() => import('@components/DiscordAvatar'))
@ -98,7 +98,7 @@ const VoteBot: NextPage<VoteBotProps> = ({ data, user, theme, csrfToken }) => {
<Advertisement /> <Advertisement />
<Link href={makeBotURL(data)} className='text-blue-500 hover:opacity-80'> <Link href={makeBotURL(data)} className='text-blue-500 hover:opacity-80'>
<i className='fas fa-arrow-left mb-3 mt-3' /> <strong>{data.name}</strong> <i className='fas fa-arrow-left mb-3 mt-3' /> <strong>{data.name}</strong>
{getJosaPicker('로')(data.name)} {getJosaPicker('로')(data.name)}
</Link> </Link>
<Segment className='mb-16 py-8'> <Segment className='mb-16 py-8'>
<div className='text-center'> <div className='text-center'>

10
pages/bots/koreanbots.tsx Normal file
View File

@ -0,0 +1,10 @@
import { NextPage } from 'next'
import { useRouter } from 'next/router'
const Reserved: NextPage = () => {
const router = useRouter()
router.push('/bots/iu')
return <></>
}
export default Reserved

View File

@ -42,7 +42,7 @@ const Security: NextPage<SecurityProps> = ({ bugReports }) => {
</ul> </ul>
<h1 className='mb-3 mt-6 text-3xl font-bold text-koreanbots-blue'></h1> <h1 className='mb-3 mt-6 text-3xl font-bold text-koreanbots-blue'></h1>
<ul className='list-inside list-disc'> <ul className='list-inside list-disc'>
{['koreanbots.dev 및 *.koreanbots.dev', 'listing.kr', 'discordlist.kr', '디스코드.한국'].map((el) => ( {['koreanbots.dev 및 *.koreanbots.dev', 'kbots.link', '디스코드.한국'].map((el) => (
<li key={el}>{el}</li> <li key={el}>{el}</li>
))} ))}
</ul> </ul>

View File

@ -42,8 +42,7 @@ const Servers: NextPage<ServersProps> = ({ data, desc, date, user, theme }) => {
const [emojisModal, setEmojisModal] = useState(false) const [emojisModal, setEmojisModal] = useState(false)
const [ownersModal, setOwnersModal] = useState(false) const [ownersModal, setOwnersModal] = useState(false)
const [owners, setOwners] = useState<User[]>(null) const [owners, setOwners] = useState<User[]>(null)
const bg = const bg = checkBotFlag(data?.flags, 'trusted') && data?.banner
(checkBotFlag(data?.flags, 'trusted') || checkBotFlag(data?.flags, 'partnered')) && data?.bg
const router = useRouter() const router = useRouter()
useEffect(() => { useEffect(() => {
if (data) if (data)
@ -144,12 +143,7 @@ const Servers: NextPage<ServersProps> = ({ data, desc, date, user, theme }) => {
</div> </div>
<div className='w-full lg:flex'> <div className='w-full lg:flex'>
<div className='w-full text-center lg:w-2/12'> <div className='w-full text-center lg:w-2/12'>
<ServerIcon <ServerIcon id={data.id} size={256} className='w-full rounded-full' hash={data.icon} />
id={data.id}
size={256}
className='w-full rounded-full'
hash={data.icon}
/>
</div> </div>
<div className='w-full grow px-5 py-12 text-center lg:w-5/12 lg:text-left'> <div className='w-full grow px-5 py-12 text-center lg:w-5/12 lg:text-left'>
<h1 className='mb-2 mt-3 text-4xl font-bold' style={bg ? { color: 'white' } : {}}> <h1 className='mb-2 mt-3 text-4xl font-bold' style={bg ? { color: 'white' } : {}}>

View File

@ -1,23 +1,23 @@
import { Field, Form, Formik } from 'formik'
import { NextPage } from 'next' import { NextPage } from 'next'
import dynamic from 'next/dynamic'
import Link from 'next/link' import Link from 'next/link'
import dynamic from 'next/dynamic'
import { Field, Form, Formik } from 'formik'
import { CsrfContext, ResponseProps, Server, User } from '@types' import { Server, CsrfContext, ResponseProps, User } from '@types'
import { get } from '@utils/Query' import { get } from '@utils/Query'
import { makeServerURL, parseCookie } from '@utils/Tools' import { makeServerURL, parseCookie } from '@utils/Tools'
import { ParsedUrlQuery } from 'querystring' import { ParsedUrlQuery } from 'querystring'
import { DMCA, TextField } from '@components/ReportTemplate' import NotFound from 'pages/404'
import { serverReportCats } from '@utils/Constants'
import { getToken } from '@utils/Csrf' import { getToken } from '@utils/Csrf'
import { DMCA, TextField } from '@components/ReportTemplate'
import { useState } from 'react'
import Fetch from '@utils/Fetch' import Fetch from '@utils/Fetch'
import { ReportSchema } from '@utils/Yup' import { ReportSchema } from '@utils/Yup'
import { getJosaPicker } from 'josa' import { getJosaPicker } from 'josa'
import { serverReportCats } from '@utils/Constants'
import { NextSeo } from 'next-seo' import { NextSeo } from 'next-seo'
import NotFound from 'pages/404'
import { useState } from 'react'
const Container = dynamic(() => import('@components/Container')) const Container = dynamic(() => import('@components/Container'))
const Message = dynamic(() => import('@components/Message')) const Message = dynamic(() => import('@components/Message'))
@ -37,7 +37,7 @@ const ReportServer: NextPage<ReportServerProps> = ({ data, user, csrfToken }) =>
<NextSeo title={`${data.name} 신고하기`} /> <NextSeo title={`${data.name} 신고하기`} />
<Link href={makeServerURL(data)} className='text-blue-500 hover:opacity-80'> <Link href={makeServerURL(data)} className='text-blue-500 hover:opacity-80'>
<i className='fas fa-arrow-left mb-3 mt-3' /> <strong>{data.name}</strong> <i className='fas fa-arrow-left mb-3 mt-3' /> <strong>{data.name}</strong>
{getJosaPicker('로')(data.name)} {getJosaPicker('로')(data.name)}
</Link> </Link>
{reportRes?.code === 200 ? ( {reportRes?.code === 200 ? (
<Message type='success'> <Message type='success'>

View File

@ -1,24 +1,24 @@
import { NextPage } from 'next' import { NextPage } from 'next'
import dynamic from 'next/dynamic'
import Link from 'next/link' import Link from 'next/link'
import dynamic from 'next/dynamic'
import { useRouter } from 'next/router' import { useRouter } from 'next/router'
import { CsrfContext, ResponseProps, Server, Theme, User } from '@types' import { CsrfContext, ResponseProps, Server, Theme, User } from '@types'
import { get } from '@utils/Query' import { get } from '@utils/Query'
import { checkServerFlag, makeServerURL, parseCookie } from '@utils/Tools' import { parseCookie, checkServerFlag, makeServerURL } from '@utils/Tools'
import { ParsedUrlQuery } from 'querystring' import { ParsedUrlQuery } from 'querystring'
import Captcha from '@components/Captcha'
import SetNotification, { getFCMToken } from '@components/FCM'
import { KoreanbotsEndPoints } from '@utils/Constants'
import { getToken } from '@utils/Csrf'
import Day from '@utils/Day'
import Fetch from '@utils/Fetch'
import { getJosaPicker } from 'josa'
import { NextSeo } from 'next-seo'
import NotFound from 'pages/404' import NotFound from 'pages/404'
import { getToken } from '@utils/Csrf'
import Captcha from '@components/Captcha'
import { useEffect, useRef, useState } from 'react' import { useEffect, useRef, useState } from 'react'
import Fetch from '@utils/Fetch'
import Day from '@utils/Day'
import { getJosaPicker } from 'josa'
import { KoreanbotsEndPoints } from '@utils/Constants'
import { NextSeo } from 'next-seo'
import SetNotification, { getFCMToken } from '@components/FCM'
const Container = dynamic(() => import('@components/Container')) const Container = dynamic(() => import('@components/Container'))
const ServerIcon = dynamic(() => import('@components/ServerIcon')) const ServerIcon = dynamic(() => import('@components/ServerIcon'))
@ -99,7 +99,7 @@ const VoteServer: NextPage<VoteServerProps> = ({ data, user, theme, csrfToken })
<Advertisement /> <Advertisement />
<Link href={makeServerURL(data)} className='text-blue-500 hover:opacity-80'> <Link href={makeServerURL(data)} className='text-blue-500 hover:opacity-80'>
<i className='fas fa-arrow-left mb-3 mt-3' /> <strong>{data.name}</strong> <i className='fas fa-arrow-left mb-3 mt-3' /> <strong>{data.name}</strong>
{getJosaPicker('로')(data.name)} {getJosaPicker('로')(data.name)}
</Link> </Link>
<Segment className='mb-16 py-8'> <Segment className='mb-16 py-8'>
<div className='text-center'> <div className='text-center'>

View File

@ -1,7 +1,7 @@
import { Field, Form, Formik } from 'formik'
import { NextPage } from 'next' import { NextPage } from 'next'
import dynamic from 'next/dynamic'
import Link from 'next/link' import Link from 'next/link'
import dynamic from 'next/dynamic'
import { Field, Form, Formik } from 'formik'
import { CsrfContext, ResponseProps, User } from '@types' import { CsrfContext, ResponseProps, User } from '@types'
import { get } from '@utils/Query' import { get } from '@utils/Query'
@ -9,15 +9,15 @@ import { makeUserURL, parseCookie } from '@utils/Tools'
import { ParsedUrlQuery } from 'querystring' import { ParsedUrlQuery } from 'querystring'
import { DMCA, TextField } from '@components/ReportTemplate' import NotFound from 'pages/404'
import { reportCats } from '@utils/Constants'
import { getToken } from '@utils/Csrf' import { getToken } from '@utils/Csrf'
import { DMCA, TextField } from '@components/ReportTemplate'
import { useState } from 'react'
import Fetch from '@utils/Fetch' import Fetch from '@utils/Fetch'
import { ReportSchema } from '@utils/Yup' import { ReportSchema } from '@utils/Yup'
import { getJosaPicker } from 'josa' import { getJosaPicker } from 'josa'
import { reportCats } from '@utils/Constants'
import { NextSeo } from 'next-seo' import { NextSeo } from 'next-seo'
import NotFound from 'pages/404'
import { useState } from 'react'
const Container = dynamic(() => import('@components/Container')) const Container = dynamic(() => import('@components/Container'))
const Message = dynamic(() => import('@components/Message')) const Message = dynamic(() => import('@components/Message'))
@ -50,7 +50,7 @@ const ReportUser: NextPage<ReportUserProps> = ({ data, user, csrfToken }) => {
<NextSeo title={`${data.globalName} 신고하기`} /> <NextSeo title={`${data.globalName} 신고하기`} />
<Link href={makeUserURL(data)} className='text-blue-500 hover:opacity-80'> <Link href={makeUserURL(data)} className='text-blue-500 hover:opacity-80'>
<i className='fas fa-arrow-left mb-3 mt-3' /> <strong>{data.globalName}</strong> <i className='fas fa-arrow-left mb-3 mt-3' /> <strong>{data.globalName}</strong>
{getJosaPicker('로')(data.globalName)} {getJosaPicker('로')(data.globalName)}
</Link> </Link>
{reportRes?.code === 200 ? ( {reportRes?.code === 200 ? (
<Message type='success'> <Message type='success'>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 61 KiB

2
types/global.d.ts vendored
View File

@ -2,7 +2,6 @@
import * as Yup from 'yup' import * as Yup from 'yup'
import { Client } from 'discord.js' import { Client } from 'discord.js'
import NotificationManager from '@utils/NotificationManager' import NotificationManager from '@utils/NotificationManager'
import { CacheManager } from '@utils/Query'
declare global { declare global {
interface Window { interface Window {
@ -15,7 +14,6 @@ declare global {
var kodl: Client var kodl: Client
var serverlist: Client var serverlist: Client
var notification: NotificationManager var notification: NotificationManager
var get: CacheManager
interface Navigator { interface Navigator {
standalone?: boolean standalone?: boolean
} }

View File

@ -1,12 +1,9 @@
import { botEnforcements } from '@utils/Constants'
import type { GuildFeature } from 'discord.js' import type { GuildFeature } from 'discord.js'
import type { IncomingMessage } from 'http' import type { IncomingMessage } from 'http'
import type { NextPageContext } from 'next' import type { NextPageContext } from 'next'
export type Nullable<T> = T | null export type Nullable<T> = T | null
export type ValueOf<T> = T[keyof T]
export interface Bot { export interface Bot {
id: string id: string
name: string name: string
@ -28,14 +25,11 @@ export interface Bot {
url: string | null url: string | null
discord: string | null discord: string | null
vanity: string | null vanity: string | null
enforcements: BotEnforcementKeys[]
bg: string bg: string
banner: string banner: string
owners: User[] | string[] owners: User[] | string[]
} }
export type BotEnforcementKeys = keyof typeof botEnforcements
export interface RawGuild { export interface RawGuild {
id: string id: string
name: string name: string
@ -95,8 +89,6 @@ export interface BotSpec {
webhookURL: string | null webhookURL: string | null
webhookStatus: WebhookStatus webhookStatus: WebhookStatus
token: string token: string
banner: string | null
bg: string | null
} }
export interface ServerSpec { export interface ServerSpec {
@ -359,7 +351,7 @@ export interface ImageOptions {
export interface KoreanbotsImageOptions { export interface KoreanbotsImageOptions {
format?: 'webp' | 'png' | 'gif' format?: 'webp' | 'png' | 'gif'
size?: 128 | 256 | 512 size?: 128 | 256 | 512
hash?: string hash?: string;
} }
export enum DiscordImageType { export enum DiscordImageType {

View File

@ -102,7 +102,7 @@ export const botCategoryDescription = {
: '게임 유저 전적이나 게임 정보 등 여러 전적에 대해 다룹니다.', : '게임 유저 전적이나 게임 정보 등 여러 전적에 대해 다룹니다.',
: '봇에 자체적인 게임 콘텐츠가 있습니다.', : '봇에 자체적인 게임 콘텐츠가 있습니다.',
: '봇 내 가상 재화를 이용해 도박을 할 수 있습니다.', : '봇 내 가상 재화를 이용해 도박을 할 수 있습니다.',
: '유저의 출입, 메시지 수정 / 삭제 등 각종 기록을 디스코드 채널에 남길 수 있습니다.', : '유저의 출입, 메시지 수정 / 삭제 등을 로그로 남길 수 있습니다.',
'빗금 명령어': '메시지 기반이 아닌 빗금 명령어를 사용합니다.', '빗금 명령어': '메시지 기반이 아닌 빗금 명령어를 사용합니다.',
'웹 대시보드': '웹사이트를 통해 봇을 조작할 수 있습니다.', '웹 대시보드': '웹사이트를 통해 봇을 조작할 수 있습니다.',
: '각종 밈을 다루고 있습니다.', : '각종 밈을 다루고 있습니다.',
@ -120,29 +120,6 @@ export const botCategoryDescription = {
: '게임 "마인크래프트"에 관련된 기능을 다룹니다.', : '게임 "마인크래프트"에 관련된 기능을 다룹니다.',
} }
export const botEnforcements = {
NONE: {
label: '해당사항이 없습니다.',
description: '',
},
JOIN_PARTIALLY_ENFORCED: {
label: '지정된 서버에 참여해야만 사용이 가능한 기능이 있습니다',
description: '봇의 일부 명령어는 봇이 지정한 특정 디스코드 서버에 참여해야 사용할 수 있습니다.',
},
JOIN_ENFORCED: {
label: '지정된 서버에 참여하지 않으면 봇의 핵심 기능을 사용할 수 없습니다',
description: '봇의 핵심 기능은 봇이 지정한 특정 디스코드 서버에 참여해야 사용할 수 있습니다.',
},
LICENSE_PARTIALLY_ENFORCED: {
label: '유료 구매가 필요한 기능이 있습니다',
description: '봇의 일부 명령어는 유료 구매가 필요합니다.',
},
LICENSE_ENFORCED: {
label: '유료 구매 없이는 봇의 핵심 기능을 사용할 수 없습니다',
description: '유료 구매 없이는 봇의 핵심 기능을 사용할 수 없습니다.',
},
} as const
export const botCategoryIcon = { export const botCategoryIcon = {
: 'fas fa-cogs', : 'fas fa-cogs',
: 'fas fa-music', : 'fas fa-music',
@ -649,10 +626,3 @@ export const GuildPermissions = {
}, },
], ],
} }
export const reservedVanityBypass = [
'653534001742741552',
'784618064167698472',
'653083797763522580',
'807561475014262785',
]

View File

@ -57,10 +57,6 @@ export const webhookClients = {
{ url: process.env.REPORT_WEBHOOK_URL ?? dummyURL }, { url: process.env.REPORT_WEBHOOK_URL ?? dummyURL },
{ allowedMentions: { parse: [] } } { allowedMentions: { parse: [] } }
), ),
noticeLog: new Discord.WebhookClient(
{ url: process.env.NOTICE_LOG_WEBHOOK_URL ?? dummyURL },
{ allowedMentions: { parse: [] } }
),
}, },
} }

View File

@ -3,7 +3,6 @@ import knex from 'knex'
export default knex({ export default knex({
client: 'mysql', client: 'mysql',
connection: { connection: {
port: Number(process.env.MYSQL_PORT) || 3306,
host: process.env.MYSQL_HOST || 'localhost', host: process.env.MYSQL_HOST || 'localhost',
user: process.env.MYSQL_USER || 'root', user: process.env.MYSQL_USER || 'root',
password: process.env.MYSQL_PASSWORD || 'test', password: process.env.MYSQL_PASSWORD || 'test',

View File

@ -62,7 +62,6 @@ async function getBot(id: string, topLevel = true): Promise<Bot> {
'bots.status', 'bots.status',
'bots.trusted', 'bots.trusted',
'bots.partnered', 'bots.partnered',
'bots.enforcements',
'bots.discord', 'bots.discord',
'bots.state', 'bots.state',
'bots.vanity', 'bots.vanity',
@ -101,9 +100,7 @@ async function getBot(id: string, topLevel = true): Promise<Bot> {
res.name = name res.name = name
res.category = JSON.parse(res.category) res.category = JSON.parse(res.category)
res.owners = JSON.parse(res.owners) 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) { if (discordBot.flags.bitfield & UserFlags.BotHTTPInteractions) {
res.status = 'online' res.status = 'online'
} else if (botMember) { } else if (botMember) {
@ -449,7 +446,6 @@ async function getBotSubmit(id: string, date: number): Promise<SubmittedBot> {
'id', 'id',
'date', 'date',
'category', 'category',
'enforcements',
'lib', 'lib',
'prefix', 'prefix',
'intro', 'intro',
@ -465,7 +461,6 @@ async function getBotSubmit(id: string, date: number): Promise<SubmittedBot> {
.where({ id, date }) .where({ id, date })
if (res.length === 0) return null if (res.length === 0) return null
res[0].category = JSON.parse(res[0].category) 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) res[0].owner = await get.user.load(res[0].owner)
return res[0] return res[0]
} }
@ -477,7 +472,6 @@ async function getBotSubmits(id: string): Promise<SubmittedBot[]> {
'id', 'id',
'date', 'date',
'category', 'category',
'enforcements',
'lib', 'lib',
'prefix', 'prefix',
'intro', 'intro',
@ -496,7 +490,6 @@ async function getBotSubmits(id: string): Promise<SubmittedBot[]> {
res = await Promise.all( res = await Promise.all(
res.map(async (el) => { res.map(async (el) => {
el.category = JSON.parse(el.category) el.category = JSON.parse(el.category)
el.enforcements = JSON.parse(el.enforcements)
el.owner = owner el.owner = owner
return el return el
}) })
@ -641,7 +634,6 @@ async function submitBot(
git: data.git, git: data.git,
url: data.url, url: data.url,
category: JSON.stringify(data.category), category: JSON.stringify(data.category),
enforcements: JSON.stringify(data.enforcements),
discord: data.discord, discord: data.discord,
state: 0, state: 0,
}) })
@ -684,14 +676,7 @@ async function submitServer(
async function getBotSpec(id: string, userID: string): Promise<BotSpec | null> { async function getBotSpec(id: string, userID: string): Promise<BotSpec | null> {
const res = await knex('bots') const res = await knex('bots')
.select([ .select(['bots.id', 'bots.token', 'bots.webhook_url', 'bots.webhook_status'])
'bots.id',
'bots.token',
'bots.webhook_url',
'bots.webhook_status',
'bots.banner',
'bots.bg',
])
.leftJoin('owners_mapping', 'bots.id', 'owners_mapping.target_id') .leftJoin('owners_mapping', 'bots.id', 'owners_mapping.target_id')
.where('owners_mapping.user_id', userID) .where('owners_mapping.user_id', userID)
.andWhere('owners_mapping.type', ObjectType.Bot) .andWhere('owners_mapping.type', ObjectType.Bot)
@ -703,8 +688,6 @@ async function getBotSpec(id: string, userID: string): Promise<BotSpec | null> {
token: res[0].token, token: res[0].token,
webhookURL: res[0].webhook_url, webhookURL: res[0].webhook_url,
webhookStatus: res[0].webhook_status, webhookStatus: res[0].webhook_status,
banner: res[0].banner,
bg: res[0].bg,
} }
} }
@ -750,10 +733,6 @@ async function updateBot(id: string, data: ManageBot): Promise<number> {
category: JSON.stringify(data.category), category: JSON.stringify(data.category),
intro: data.intro, intro: data.intro,
desc: data.desc, desc: data.desc,
vanity: data.vanity,
enforcements: JSON.stringify(data.enforcements),
banner: data.banner,
bg: data.bg,
}) })
.where({ id }) .where({ id })
@ -1141,7 +1120,6 @@ async function approveBotSubmission(id: string, date: number) {
'id', 'id',
'date', 'date',
'category', 'category',
'enforcements',
'lib', 'lib',
'prefix', 'prefix',
'intro', 'intro',
@ -1168,7 +1146,6 @@ async function approveBotSubmission(id: string, date: number) {
web: data.web, web: data.web,
git: data.git, git: data.git,
category: data.category, category: data.category,
enforcements: data.enforcements,
discord: data.discord, discord: data.discord,
token: sign({ id }), token: sign({ id }),
}) })
@ -1208,7 +1185,7 @@ async function viewBot(id: string) {
await Bots.findByIdAndUpdate(id, { $push: { viewMetrix: { count: 0 } } }, { upsert: true }) await Bots.findByIdAndUpdate(id, { $push: { viewMetrix: { count: 0 } } }, { upsert: true })
} }
const _get = { export const get = {
discord: { discord: {
user: new DataLoader( user: new DataLoader(
async (ids: string[]) => async (ids: string[]) =>
@ -1423,14 +1400,6 @@ const _get = {
}, },
} }
export type CacheManager = typeof _get
if (!global.get) {
global.get = _get
}
export const get = global.get
export const update = { export const update = {
assignToken, assignToken,
resetBotToken, resetBotToken,

View File

@ -1,12 +1,4 @@
import urlRegex from 'url-regex-safe' import urlRegex from 'url-regex-safe'
const reservedVanityConst = [
'koreanbots',
'koreanservers',
'koreanlist',
'kbots',
'kodl',
'discord',
]
export const ID = /^[0-9]{17,}$/ export const ID = /^[0-9]{17,}$/
export const Vanity = /^[A-Za-z\d-]+$/ export const Vanity = /^[A-Za-z\d-]+$/
@ -20,4 +12,3 @@ export const Heading = '<h\\d id="(.+?)">(.*?)<\\/h(\\d)>'
export const EmojiSyntax = ':(\\w+):' export const EmojiSyntax = ':(\\w+):'
export const ImageTag = /<img\s[^>]*?alt\s*=\s*['"]([^'"]*?)['"][^>]*?>/ export const ImageTag = /<img\s[^>]*?alt\s*=\s*['"]([^'"]*?)['"][^>]*?>/
export const markdownImage = /!\[([^\]]*)\]\((.*?)\s*("(?:.*[^"])")?\s*\)/g export const markdownImage = /!\[([^\]]*)\]\((.*?)\s*("(?:.*[^"])")?\s*\)/g
export const reservedVanity = new RegExp(`^((?!${reservedVanityConst.join('|')}).)*$`, 'i') // 예약되지 않음을 확인

View File

@ -1,15 +1,8 @@
import * as Yup from 'yup' import * as Yup from 'yup'
import YupKorean from 'yup-locales-ko' import YupKorean from 'yup-locales-ko'
import { ListType } from '@types' import { ListType } from '@types'
import { import { botCategories, library, reportCats, serverCategories } from '@utils/Constants'
botCategories, import { HTTPProtocol, ID, Prefix, Url, Vanity } from '@utils/Regex'
botEnforcements,
library,
reportCats,
reservedVanityBypass,
serverCategories,
} from '@utils/Constants'
import { HTTPProtocol, ID, Prefix, reservedVanity, Url, Vanity } from '@utils/Regex'
Yup.setLocale(YupKorean) Yup.setLocale(YupKorean)
Yup.addMethod(Yup.array, 'unique', function (message, mapper = (a) => a) { Yup.addMethod(Yup.array, 'unique', function (message, mapper = (a) => a) {
@ -175,10 +168,6 @@ export const AddBotSubmitSchema: Yup.SchemaOf<AddBotSubmit> = Yup.object({
.min(100, '봇 설명은 최소 100자여야합니다.') .min(100, '봇 설명은 최소 100자여야합니다.')
.max(1500, '봇 설명은 최대 1500자여야합니다.') .max(1500, '봇 설명은 최대 1500자여야합니다.')
.required('봇 설명은 필수 항목입니다.'), .required('봇 설명은 필수 항목입니다.'),
enforcements: Yup.array(Yup.string().oneOf(Object.keys(botEnforcements)))
.min(1, '최소 한 개의 선택지를 선택해주세요.')
.unique('선택지는 중복될 수 없습니다.')
.required('강제사항 명시는 필수 선택사항입니다.'),
_csrf: Yup.string().required(), _csrf: Yup.string().required(),
_captcha: Yup.string().required(), _captcha: Yup.string().required(),
}) })
@ -195,7 +184,6 @@ export interface AddBotSubmit {
category: string | string[] category: string | string[]
intro: string intro: string
desc: string desc: string
enforcements: string[]
_csrf: string _csrf: string
_captcha: string _captcha: string
} }
@ -269,83 +257,47 @@ export interface Report {
_csrf: string _csrf: string
} }
export function getManageBotSchema(perkAvailable = false) { export const ManageBotSchema: Yup.SchemaOf<ManageBot> = Yup.object({
const common = { prefix: Yup.string()
prefix: Yup.string() .matches(Prefix, '접두사는 띄어쓰기로 시작할 수 없습니다.')
.matches(Prefix, '접두사는 띄어쓰기로 시작할 수 없습니다.') .min(1, '접두사는 최소 1자여야합니다.')
.min(1, '접두사는 최소 1자여야합니다.') .max(32, '접두사는 최대 32자까지만 가능합니다.')
.max(32, '접두사는 최대 32자까지만 가능합니다.') .required('접두사는 필수 항목입니다.'),
.required('접두사는 필수 항목입니다.'), library: Yup.string().oneOf(library).required('라이브러리는 필수 항목입니다.'),
library: Yup.string().oneOf(library).required('라이브러리는 필수 항목입니다.'), website: Yup.string()
website: Yup.string() .matches(HTTPProtocol, 'http:// 또는 https:// 로 시작해야합니다.')
.matches(HTTPProtocol, 'http:// 또는 https:// 로 시작해야합니다.') .matches(Url, '올바른 웹사이트 URL을 입력해주세요.')
.matches(Url, '올바른 웹사이트 URL을 입력해주세요.') .max(64, 'URL은 최대 64자까지만 가능합니다.')
.max(64, 'URL은 최대 64자까지만 가능합니다.') .nullable(),
.nullable(), url: Yup.string()
url: Yup.string() .matches(HTTPProtocol, 'http:// 또는 https:// 로 시작해야합니다.')
.matches(HTTPProtocol, 'http:// 또는 https:// 로 시작해야합니다.') .matches(Url, '올바른 초대링크 URL을 입력해주세요.')
.matches(Url, '올바른 초대링크 URL을 입력해주세요.') .max(612, 'URL은 최대 612자까지만 가능합니다.')
.max(612, 'URL은 최대 612자까지만 가능합니다.') .nullable(),
.nullable(), git: Yup.string()
git: Yup.string() .matches(HTTPProtocol, 'http:// 또는 https:// 로 시작해야합니다.')
.matches(HTTPProtocol, 'http:// 또는 https:// 로 시작해야합니다.') .matches(Url, '올바른 깃 URL을 입력해주세요.')
.matches(Url, '올바른 깃 URL을 입력해주세요.') .max(64, 'URL은 최대 64자까지만 가능합니다.')
.max(64, 'URL은 최대 64자까지만 가능합니다.') .nullable(),
.nullable(), discord: Yup.string()
discord: Yup.string() .matches(Vanity, '디스코드 초대코드 형식을 지켜주세요.')
.matches(Vanity, '디스코드 초대코드 형식을 지켜주세요.') .min(2, '지원 디스코드는 최소 2자여야합니다.')
.min(2, '지원 디스코드는 최소 2자여야합니다.') .max(32, '지원 디스코드는 최대 32자까지만 가능합니다.')
.max(32, '지원 디스코드는 최대 32자까지만 가능합니다.') .nullable(),
.nullable(), category: Yup.array(Yup.string().oneOf(botCategories))
category: Yup.array(Yup.string().oneOf(botCategories)) .min(1, '최소 한 개의 카테고리를 선택해주세요.')
.min(1, '최소 한 개의 카테고리를 선택해주세요.') .unique('카테고리는 중복될 수 없습니다.')
.unique('카테고리는 중복될 수 없습니다.') .required('카테고리는 필수 항목입니다.'),
.required('카테고리는 필수 항목입니다.'), intro: Yup.string()
intro: Yup.string() .min(2, '봇 소개는 최소 2자여야합니다.')
.min(2, '봇 소개는 최소 2자여야합니다.') .max(60, '봇 소개는 최대 60자여야합니다.')
.max(60, '봇 소개는 최대 60자여야합니다.') .required('봇 소개는 필수 항목입니다.'),
.required('봇 소개는 필수 항목입니다.'), desc: Yup.string()
desc: Yup.string() .min(100, '봇 설명은 최소 100자여야합니다.')
.min(100, '봇 설명은 최소 100자여야합니다.') .max(1500, '봇 설명은 최대 1500자여야합니다.')
.max(1500, '봇 설명은 최대 1500자여야합니다.') .required('봇 설명은 필수 항목입니다.'),
.required('봇 설명은 필수 항목입니다.'), _csrf: Yup.string().required(),
enforcements: Yup.array(Yup.string().oneOf(Object.keys(botEnforcements))) })
.min(1, '최소 한 개의 선택지를 선택해주세요.')
.unique('선택지는 중복될 수 없습니다.')
.required('강제사항 명시는 필수 선택사항입니다.'),
_csrf: Yup.string().required(),
}
const perk = {
vanity: Yup.string()
.matches(Vanity, '커스텀 URL은 영문만 포함할 수 있습니다.')
.when('id', {
is: (id: string) => reservedVanityBypass.includes(id),
then: Yup.string(),
otherwise: Yup.string().matches(
reservedVanity,
'예약어가 포함되었거나 사용할 수 없는 커스텀 URL입니다.'
),
})
.min(2, '커스텀 URL은 최소 2자여야합니다.')
.max(32, '커스텀 URL은 최대 32자여야합니다.')
.nullable(),
banner: Yup.string()
.matches(HTTPProtocol, 'http:// 또는 https:// 로 시작해야합니다.')
.matches(Url, '올바른 배너 URL을 입력해주세요.')
.max(612, 'URL은 최대 612자까지만 가능합니다.')
.nullable(),
bg: Yup.string()
.matches(HTTPProtocol, 'http:// 또는 https:// 로 시작해야합니다.')
.matches(Url, '올바른 배경 URL을 입력해주세요.')
.max(612, 'URL은 최대 612자까지만 가능합니다.')
.nullable(),
}
return Yup.object({
...common,
...(perkAvailable ? perk : {}),
}) as Yup.SchemaOf<ManageBot>
}
export interface ManageBot { export interface ManageBot {
prefix: string prefix: string
@ -357,10 +309,6 @@ export interface ManageBot {
category: string[] category: string[]
intro: string intro: string
desc: string desc: string
vanity: string
banner: string
enforcements: string[]
bg: string
_csrf: string _csrf: string
} }

328
yarn.lock
View File

@ -796,15 +796,6 @@
"@babel/highlight" "^7.22.13" "@babel/highlight" "^7.22.13"
chalk "^2.4.2" chalk "^2.4.2"
"@babel/code-frame@^7.26.2":
version "7.26.2"
resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.26.2.tgz#4b5fab97d33338eff916235055f0ebc21e573a85"
integrity sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==
dependencies:
"@babel/helper-validator-identifier" "^7.25.9"
js-tokens "^4.0.0"
picocolors "^1.0.0"
"@babel/compat-data@^7.17.7", "@babel/compat-data@^7.22.5": "@babel/compat-data@^7.17.7", "@babel/compat-data@^7.22.5":
version "7.22.5" version "7.22.5"
resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.22.5.tgz#b1f6c86a02d85d2dd3368a2b67c09add8cd0c255" resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.22.5.tgz#b1f6c86a02d85d2dd3368a2b67c09add8cd0c255"
@ -1040,11 +1031,6 @@
resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.22.5.tgz#533f36457a25814cf1df6488523ad547d784a99f" resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.22.5.tgz#533f36457a25814cf1df6488523ad547d784a99f"
integrity sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw== integrity sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw==
"@babel/helper-string-parser@^7.25.9":
version "7.25.9"
resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.25.9.tgz#1aabb72ee72ed35789b4bbcad3ca2862ce614e8c"
integrity sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==
"@babel/helper-validator-identifier@^7.22.20": "@babel/helper-validator-identifier@^7.22.20":
version "7.22.20" version "7.22.20"
resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz#c4ae002c61d2879e724581d96665583dbc1dc0e0" resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz#c4ae002c61d2879e724581d96665583dbc1dc0e0"
@ -1055,11 +1041,6 @@
resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.5.tgz#9544ef6a33999343c8740fa51350f30eeaaaf193" resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.5.tgz#9544ef6a33999343c8740fa51350f30eeaaaf193"
integrity sha512-aJXu+6lErq8ltp+JhkJUfk1MTGyuA4v7f3pA+BJ5HLfNC6nAQ0Cpi9uOquUj8Hehg0aUiHzWQbOVJGao6ztBAQ== integrity sha512-aJXu+6lErq8ltp+JhkJUfk1MTGyuA4v7f3pA+BJ5HLfNC6nAQ0Cpi9uOquUj8Hehg0aUiHzWQbOVJGao6ztBAQ==
"@babel/helper-validator-identifier@^7.25.9":
version "7.25.9"
resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz#24b64e2c3ec7cd3b3c547729b8d16871f22cbdc7"
integrity sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==
"@babel/helper-validator-option@^7.22.5": "@babel/helper-validator-option@^7.22.5":
version "7.22.5" version "7.22.5"
resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.22.5.tgz#de52000a15a177413c8234fa3a8af4ee8102d0ac" resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.22.5.tgz#de52000a15a177413c8234fa3a8af4ee8102d0ac"
@ -1076,12 +1057,13 @@
"@babel/types" "^7.22.5" "@babel/types" "^7.22.5"
"@babel/helpers@^7.22.5": "@babel/helpers@^7.22.5":
version "7.26.10" version "7.22.5"
resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.26.10.tgz#6baea3cd62ec2d0c1068778d63cb1314f6637384" resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.22.5.tgz#74bb4373eb390d1ceed74a15ef97767e63120820"
integrity sha512-UPYc3SauzZ3JGgj87GgZ89JVdC5dj0AoetR5Bw6wj4niittNyFh6+eOGonYvJ1ao6B8lEa3Q3klS7ADZ53bc5g== integrity sha512-pSXRmfE1vzcUIDFQcSGA5Mr+GxBV9oiRKDuDxXvWQQBCh8HoIjs/2DlDB7H8smac1IVrB9/xdXj2N3Wol9Cr+Q==
dependencies: dependencies:
"@babel/template" "^7.26.9" "@babel/template" "^7.22.5"
"@babel/types" "^7.26.10" "@babel/traverse" "^7.22.5"
"@babel/types" "^7.22.5"
"@babel/highlight@^7.22.13": "@babel/highlight@^7.22.13":
version "7.22.20" version "7.22.20"
@ -1111,13 +1093,6 @@
resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.23.0.tgz#da950e622420bf96ca0d0f2909cdddac3acd8719" resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.23.0.tgz#da950e622420bf96ca0d0f2909cdddac3acd8719"
integrity sha512-vvPKKdMemU85V9WE/l5wZEmImpCtLqbnTvqDS2U1fJ96KrxoW7KrXhNsNCblQlg8Ck4b85yxdTyelsMUgFUXiw== integrity sha512-vvPKKdMemU85V9WE/l5wZEmImpCtLqbnTvqDS2U1fJ96KrxoW7KrXhNsNCblQlg8Ck4b85yxdTyelsMUgFUXiw==
"@babel/parser@^7.26.9":
version "7.26.10"
resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.26.10.tgz#e9bdb82f14b97df6569b0b038edd436839c57749"
integrity sha512-6aQR2zGE/QFi8JpDLjUZEPYOs7+mhKXm86VaKFiLP35JQwQb6bwUE+XbvkH0EptsYhbNBSUGaUBLKqxH1xSgsA==
dependencies:
"@babel/types" "^7.26.10"
"@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@^7.22.5": "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@^7.22.5":
version "7.22.5" version "7.22.5"
resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.22.5.tgz#87245a21cd69a73b0b81bcda98d443d6df08f05e" resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.22.5.tgz#87245a21cd69a73b0b81bcda98d443d6df08f05e"
@ -1786,11 +1761,11 @@
integrity sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA== integrity sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA==
"@babel/runtime@^7.0.0", "@babel/runtime@^7.10.1", "@babel/runtime@^7.10.5", "@babel/runtime@^7.11.1", "@babel/runtime@^7.11.2", "@babel/runtime@^7.12.0", "@babel/runtime@^7.12.5", "@babel/runtime@^7.17.9", "@babel/runtime@^7.18.3", "@babel/runtime@^7.20.7", "@babel/runtime@^7.5.5", "@babel/runtime@^7.8.4", "@babel/runtime@^7.8.7": "@babel/runtime@^7.0.0", "@babel/runtime@^7.10.1", "@babel/runtime@^7.10.5", "@babel/runtime@^7.11.1", "@babel/runtime@^7.11.2", "@babel/runtime@^7.12.0", "@babel/runtime@^7.12.5", "@babel/runtime@^7.17.9", "@babel/runtime@^7.18.3", "@babel/runtime@^7.20.7", "@babel/runtime@^7.5.5", "@babel/runtime@^7.8.4", "@babel/runtime@^7.8.7":
version "7.26.10" version "7.22.5"
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.26.10.tgz#a07b4d8fa27af131a633d7b3524db803eb4764c2" resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.22.5.tgz#8564dd588182ce0047d55d7a75e93921107b57ec"
integrity sha512-2WJMeRQPHKSPemqk/awGrAiuFfzBmOIPXKizAsVhWH9YJqLZ0H+HS4c8loHGgW6utJ3E/ejXQUsiGaQy2NZ9Fw== integrity sha512-ecjvYlnAaZ/KVneE/OdKYBYfgXV3Ptu6zQWmgEF7vwKhQnvVS6bjMD2XYgj+SNvQ1GfK/pjgokfPkC/2CO8CuA==
dependencies: dependencies:
regenerator-runtime "^0.14.0" regenerator-runtime "^0.13.11"
"@babel/template@^7.22.15": "@babel/template@^7.22.15":
version "7.22.15" version "7.22.15"
@ -1810,15 +1785,6 @@
"@babel/parser" "^7.22.5" "@babel/parser" "^7.22.5"
"@babel/types" "^7.22.5" "@babel/types" "^7.22.5"
"@babel/template@^7.26.9":
version "7.26.9"
resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.26.9.tgz#4577ad3ddf43d194528cff4e1fa6b232fa609bb2"
integrity sha512-qyRplbeIpNZhmzOysF/wFMuP9sctmh2cFzRAZOn1YapxBsE1i9bJIY586R/WBLfLcmcBlM8ROBiQURnnNy+zfA==
dependencies:
"@babel/code-frame" "^7.26.2"
"@babel/parser" "^7.26.9"
"@babel/types" "^7.26.9"
"@babel/traverse@^7.22.5", "@babel/traverse@^7.7.2": "@babel/traverse@^7.22.5", "@babel/traverse@^7.7.2":
version "7.23.2" version "7.23.2"
resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.23.2.tgz#329c7a06735e144a506bdb2cad0268b7f46f4ad8" resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.23.2.tgz#329c7a06735e144a506bdb2cad0268b7f46f4ad8"
@ -1853,14 +1819,6 @@
"@babel/helper-validator-identifier" "^7.22.20" "@babel/helper-validator-identifier" "^7.22.20"
to-fast-properties "^2.0.0" to-fast-properties "^2.0.0"
"@babel/types@^7.26.10", "@babel/types@^7.26.9":
version "7.26.10"
resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.26.10.tgz#396382f6335bd4feb65741eacfc808218f859259"
integrity sha512-emqcG3vHrpxUKTrxcblR36dcrcoRDvKmnL/dCL6ZsHaShW80qxCAcNhzQZrpeM765VzEos+xOi4s+r4IXzTwdQ==
dependencies:
"@babel/helper-string-parser" "^7.25.9"
"@babel/helper-validator-identifier" "^7.25.9"
"@bcoe/v8-coverage@^0.2.3": "@bcoe/v8-coverage@^0.2.3":
version "0.2.3" version "0.2.3"
resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39" resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39"
@ -2108,40 +2066,45 @@
resolved "https://registry.yarnpkg.com/@csstools/selector-specificity/-/selector-specificity-2.2.0.tgz#2cbcf822bf3764c9658c4d2e568bd0c0cb748016" resolved "https://registry.yarnpkg.com/@csstools/selector-specificity/-/selector-specificity-2.2.0.tgz#2cbcf822bf3764c9658c4d2e568bd0c0cb748016"
integrity sha512-+OJ9konv95ClSTOJCmMZqpd5+YGsB2S+x6w3E1oaM8UuR5j8nTNHYSz8c9BEPGDOCMQYIEEGlVPj/VY64iTbGw== integrity sha512-+OJ9konv95ClSTOJCmMZqpd5+YGsB2S+x6w3E1oaM8UuR5j8nTNHYSz8c9BEPGDOCMQYIEEGlVPj/VY64iTbGw==
"@datadog/native-appsec@8.1.1": "@datadog/libdatadog@^0.3.0":
version "8.1.1" version "0.3.0"
resolved "https://registry.yarnpkg.com/@datadog/native-appsec/-/native-appsec-8.1.1.tgz#76aa34697e6ecbd3d9ef7e6938d3cdcfa689b1f3" resolved "https://registry.yarnpkg.com/@datadog/libdatadog/-/libdatadog-0.3.0.tgz#2fc1e2695872840bc8c356f66acf675da428d6f0"
integrity sha512-mf+Ym/AzET4FeUTXOs8hz0uLOSsVIUnavZPUx8YoKWK5lKgR2L+CLfEzOpjBwgFpDgbV8I1/vyoGelgGpsMKHA== integrity sha512-TbP8+WyXfh285T17FnLeLUOPl4SbkRYMqKgcmknID2mXHNrbt5XJgW9bnDgsrrtu31Q7FjWWw2WolgRLWyzLRA==
"@datadog/native-appsec@8.3.0":
version "8.3.0"
resolved "https://registry.yarnpkg.com/@datadog/native-appsec/-/native-appsec-8.3.0.tgz#91afd89d18d386be4da8a1b0e04500f2f8b5eb66"
integrity sha512-RYHbSJ/MwJcJaLzaCaZvUyNLUKFbMshayIiv4ckpFpQJDiq1T8t9iM2k7008s75g1vRuXfsRNX7MaLn4aoFuWA==
dependencies: dependencies:
node-gyp-build "^3.9.0" node-gyp-build "^3.9.0"
"@datadog/native-iast-rewriter@2.5.0": "@datadog/native-iast-rewriter@2.6.1":
version "2.5.0" version "2.6.1"
resolved "https://registry.yarnpkg.com/@datadog/native-iast-rewriter/-/native-iast-rewriter-2.5.0.tgz#b613defe86e78168f750d1f1662d4ffb3cf002e6" resolved "https://registry.yarnpkg.com/@datadog/native-iast-rewriter/-/native-iast-rewriter-2.6.1.tgz#5e5393628c73c57dcf08256299c0e8cf71deb14f"
integrity sha512-WRu34A3Wwp6oafX8KWNAbedtDaaJO+nzfYQht7pcJKjyC2ggfPeF7SoP+eDo9wTn4/nQwEOscSR4hkJqTRlpXQ== integrity sha512-zv7cr/MzHg560jhAnHcO7f9pLi4qaYrBEcB+Gla0xkVouYSDsp8cGXIGG4fiGdAMHdt7SpDNS6+NcEAqD/v8Ig==
dependencies: dependencies:
lru-cache "^7.14.0" lru-cache "^7.14.0"
node-gyp-build "^4.5.0" node-gyp-build "^4.5.0"
"@datadog/native-iast-taint-tracking@3.1.0": "@datadog/native-iast-taint-tracking@3.2.0":
version "3.1.0" version "3.2.0"
resolved "https://registry.yarnpkg.com/@datadog/native-iast-taint-tracking/-/native-iast-taint-tracking-3.1.0.tgz#7b2ed7f8fad212d65e5ab03bcdea8b42a3051b2e" resolved "https://registry.yarnpkg.com/@datadog/native-iast-taint-tracking/-/native-iast-taint-tracking-3.2.0.tgz#9fb6823d82f934e12c06ea1baa7399ca80deb2ec"
integrity sha512-rw6qSjmxmu1yFHVvZLXFt/rVq2tUZXocNogPLB8n7MPpA0jijNGb109WokWw5ITImiW91GcGDuBW6elJDVKouQ== integrity sha512-Mc6FzCoyvU5yXLMsMS9yKnEqJMWoImAukJXolNWCTm+JQYCMf2yMsJ8pBAm7KyZKliamM9rCn7h7Tr2H3lXwjA==
dependencies: dependencies:
node-gyp-build "^3.9.0" node-gyp-build "^3.9.0"
"@datadog/native-metrics@^2.0.0": "@datadog/native-metrics@^3.1.0":
version "2.0.0" version "3.1.0"
resolved "https://registry.yarnpkg.com/@datadog/native-metrics/-/native-metrics-2.0.0.tgz#65bf03313ee419956361e097551db36173e85712" resolved "https://registry.yarnpkg.com/@datadog/native-metrics/-/native-metrics-3.1.0.tgz#c2378841accd9fdd6866d0e49bdf6e3d76e79f22"
integrity sha512-YklGVwUtmKGYqFf1MNZuOHvTYdKuR4+Af1XkWcMD8BwOAjxmd9Z+97328rCOY8TFUJzlGUPaXzB8j2qgG/BMwA== integrity sha512-yOBi4x0OQRaGNPZ2bx9TGvDIgEdQ8fkudLTFAe7gEM1nAlvFmbE5YfpH8WenEtTSEBwojSau06m2q7axtEEmCg==
dependencies: dependencies:
node-addon-api "^6.1.0" node-addon-api "^6.1.0"
node-gyp-build "^3.9.0" node-gyp-build "^3.9.0"
"@datadog/pprof@5.3.0": "@datadog/pprof@5.4.1":
version "5.3.0" version "5.4.1"
resolved "https://registry.yarnpkg.com/@datadog/pprof/-/pprof-5.3.0.tgz#c2f58d328ecced7f99887f1a559d7fe3aecb9219" resolved "https://registry.yarnpkg.com/@datadog/pprof/-/pprof-5.4.1.tgz#08c9bcf5d8efb2eeafdfc9f5bb5402f79fb41266"
integrity sha512-53z2Q3K92T6Pf4vz4Ezh8kfkVEvLzbnVqacZGgcbkP//q0joFzO8q00Etw1S6NdnCX0XmX08ULaF4rUI5r14mw== integrity sha512-IvpL96e/cuh8ugP5O8Czdup7XQOLHeIDgM5pac5W7Lc1YzGe5zTtebKFpitvb1CPw1YY+1qFx0pWGgKP2kOfHg==
dependencies: dependencies:
delay "^5.0.0" delay "^5.0.0"
node-gyp-build "<4.0" node-gyp-build "<4.0"
@ -2912,6 +2875,11 @@
wrap-ansi "^8.1.0" wrap-ansi "^8.1.0"
wrap-ansi-cjs "npm:wrap-ansi@^7.0.0" wrap-ansi-cjs "npm:wrap-ansi@^7.0.0"
"@isaacs/ttlcache@^1.4.1":
version "1.4.1"
resolved "https://registry.yarnpkg.com/@isaacs/ttlcache/-/ttlcache-1.4.1.tgz#21fb23db34e9b6220c6ba023a0118a2dd3461ea2"
integrity sha512-RQgQ4uQ+pLbqXfOmieB91ejmLwvSgv9nLx6sT6sD83s7umBypgg+OIBOBbEUiJXrfpnp9j0mRhYYdzp9uqq3lA==
"@istanbuljs/load-nyc-config@^1.0.0": "@istanbuljs/load-nyc-config@^1.0.0":
version "1.1.0" version "1.1.0"
resolved "https://registry.yarnpkg.com/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz#fd3db1d59ecf7cf121e80650bb86712f9b55eced" resolved "https://registry.yarnpkg.com/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz#fd3db1d59ecf7cf121e80650bb86712f9b55eced"
@ -3177,10 +3145,10 @@
dependencies: dependencies:
sparse-bitfield "^3.0.3" sparse-bitfield "^3.0.3"
"@next/env@14.2.32": "@next/env@14.2.22":
version "14.2.32" version "14.2.22"
resolved "https://registry.yarnpkg.com/@next/env/-/env-14.2.32.tgz#6d1107e2b7cc8649ff3730b8b46deb4e8a6d38fa" resolved "https://registry.yarnpkg.com/@next/env/-/env-14.2.22.tgz#8898ae47595badbfacebfc1585f42a4e06a97301"
integrity sha512-n9mQdigI6iZ/DF6pCTwMKeWgF2e8lg7qgt5M7HXMLtyhZYMnf/u905M18sSpPmHL9MKp9JHo56C6jrD2EvWxng== integrity sha512-EQ6y1QeNQglNmNIXvwP/Bb+lf7n9WtgcWvtoFsHquVLCJUuxRs+6SfZ5EK0/EqkkLex4RrDySvKgKNN7PXip7Q==
"@next/eslint-plugin-next@13.4.7": "@next/eslint-plugin-next@13.4.7":
version "13.4.7" version "13.4.7"
@ -3189,50 +3157,50 @@
dependencies: dependencies:
glob "7.1.7" glob "7.1.7"
"@next/swc-darwin-arm64@14.2.32": "@next/swc-darwin-arm64@14.2.22":
version "14.2.32" version "14.2.22"
resolved "https://registry.yarnpkg.com/@next/swc-darwin-arm64/-/swc-darwin-arm64-14.2.32.tgz#83482a7282df899b73d916e02b02a189771e706c" resolved "https://registry.yarnpkg.com/@next/swc-darwin-arm64/-/swc-darwin-arm64-14.2.22.tgz#2b3fcb42247ba951b19a48fc03f1d6fe65629baa"
integrity sha512-osHXveM70zC+ilfuFa/2W6a1XQxJTvEhzEycnjUaVE8kpUS09lDpiDDX2YLdyFCzoUbvbo5r0X1Kp4MllIOShw== integrity sha512-HUaLiehovgnqY4TMBZJ3pDaOsTE1spIXeR10pWgdQVPYqDGQmHJBj3h3V6yC0uuo/RoY2GC0YBFRkOX3dI9WVQ==
"@next/swc-darwin-x64@14.2.32": "@next/swc-darwin-x64@14.2.22":
version "14.2.32" version "14.2.22"
resolved "https://registry.yarnpkg.com/@next/swc-darwin-x64/-/swc-darwin-x64-14.2.32.tgz#1a9eb676a014e1fc999251f10288c25a0f81d6d1" resolved "https://registry.yarnpkg.com/@next/swc-darwin-x64/-/swc-darwin-x64-14.2.22.tgz#11ecc609e9530b3edf8ddfd1fd3bd6aca4e1bfda"
integrity sha512-P9NpCAJuOiaHHpqtrCNncjqtSBi1f6QUdHK/+dNabBIXB2RUFWL19TY1Hkhu74OvyNQEYEzzMJCMQk5agjw1Qg== integrity sha512-ApVDANousaAGrosWvxoGdLT0uvLBUC+srqOcpXuyfglA40cP2LBFaGmBjhgpxYk5z4xmunzqQvcIgXawTzo2uQ==
"@next/swc-linux-arm64-gnu@14.2.32": "@next/swc-linux-arm64-gnu@14.2.22":
version "14.2.32" version "14.2.22"
resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-14.2.32.tgz#7713a49abd555d6f698e766b1631b67d881b4ee4" resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-14.2.22.tgz#4c08dd223e50c348f561af2285e27fb326ffabbf"
integrity sha512-v7JaO0oXXt6d+cFjrrKqYnR2ubrD+JYP7nQVRZgeo5uNE5hkCpWnHmXm9vy3g6foMO8SPwL0P3MPw1c+BjbAzA== integrity sha512-3O2J99Bk9aM+d4CGn9eEayJXHuH9QLx0BctvWyuUGtJ3/mH6lkfAPRI4FidmHMBQBB4UcvLMfNf8vF0NZT7iKw==
"@next/swc-linux-arm64-musl@14.2.32": "@next/swc-linux-arm64-musl@14.2.22":
version "14.2.32" version "14.2.22"
resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-14.2.32.tgz#327efdffe97e56f5389a7889cdedbd676fdbb519" resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-14.2.22.tgz#0b285336f145887d421b3762f3d7c75f847ec1b3"
integrity sha512-tA6sIKShXtSJBTH88i0DRd6I9n3ZTirmwpwAqH5zdJoQF7/wlJXR8DkPmKwYl5mFWhEKr5IIa3LfpMW9RRwKmQ== integrity sha512-H/hqfRz75yy60y5Eg7DxYfbmHMjv60Dsa6IWHzpJSz4MRkZNy5eDnEW9wyts9bkxwbOVZNPHeb3NkqanP+nGPg==
"@next/swc-linux-x64-gnu@14.2.32": "@next/swc-linux-x64-gnu@14.2.22":
version "14.2.32" version "14.2.22"
resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-14.2.32.tgz#a3e7444613d0fe5c8ea4ead08d6a9c818246758c" resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-14.2.22.tgz#a936b6cfea0364571102f0389c6368d6acf3e294"
integrity sha512-7S1GY4TdnlGVIdeXXKQdDkfDysoIVFMD0lJuVVMeb3eoVjrknQ0JNN7wFlhCvea0hEk0Sd4D1hedVChDKfV2jw== integrity sha512-LckLwlCLcGR1hlI5eiJymR8zSHPsuruuwaZ3H2uudr25+Dpzo6cRFjp/3OR5UYJt8LSwlXv9mmY4oI2QynwpqQ==
"@next/swc-linux-x64-musl@14.2.32": "@next/swc-linux-x64-musl@14.2.22":
version "14.2.32" version "14.2.22"
resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-14.2.32.tgz#a2ec5b0a06c740d6740c938b1d4a614f1a13f018" resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-14.2.22.tgz#0359497840d0b7d8c095d0d9735bc6aec68cef5d"
integrity sha512-OHHC81P4tirVa6Awk6eCQ6RBfWl8HpFsZtfEkMpJ5GjPsJ3nhPe6wKAJUZ/piC8sszUkAgv3fLflgzPStIwfWg== integrity sha512-qGUutzmh0PoFU0fCSu0XYpOfT7ydBZgDfcETIeft46abPqP+dmePhwRGLhFKwZWxNWQCPprH26TjaTxM0Nv8mw==
"@next/swc-win32-arm64-msvc@14.2.32": "@next/swc-win32-arm64-msvc@14.2.22":
version "14.2.32" version "14.2.22"
resolved "https://registry.yarnpkg.com/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-14.2.32.tgz#b4d3e47c6b276fc4711deb978d04015d029d198d" resolved "https://registry.yarnpkg.com/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-14.2.22.tgz#9fd249d49ffccf3388400ab24472c432cdd04c24"
integrity sha512-rORQjXsAFeX6TLYJrCG5yoIDj+NKq31Rqwn8Wpn/bkPNy5rTHvOXkW8mLFonItS7QC6M+1JIIcLe+vOCTOYpvg== integrity sha512-K6MwucMWmIvMb9GlvT0haYsfIPxfQD8yXqxwFy4uLFMeXIb2TcVYQimxkaFZv86I7sn1NOZnpOaVk5eaxThGIw==
"@next/swc-win32-ia32-msvc@14.2.32": "@next/swc-win32-ia32-msvc@14.2.22":
version "14.2.32" version "14.2.22"
resolved "https://registry.yarnpkg.com/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-14.2.32.tgz#d1f1f854a1fbbaeefa8f81271437448653f33494" resolved "https://registry.yarnpkg.com/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-14.2.22.tgz#70d8d5a48e78c7382c3e0544af28c2788ca6b551"
integrity sha512-jHUeDPVHrgFltqoAqDB6g6OStNnFxnc7Aks3p0KE0FbwAvRg6qWKYF5mSTdCTxA3axoSAUwxYdILzXJfUwlHhA== integrity sha512-5IhDDTPEbzPR31ZzqHe90LnNe7BlJUZvC4sA1thPJV6oN5WmtWjZ0bOYfNsyZx00FJt7gggNs6SrsX0UEIcIpA==
"@next/swc-win32-x64-msvc@14.2.32": "@next/swc-win32-x64-msvc@14.2.22":
version "14.2.32" version "14.2.22"
resolved "https://registry.yarnpkg.com/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-14.2.32.tgz#8212d681cf6858a9e3204728f8f2b161000683ed" resolved "https://registry.yarnpkg.com/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-14.2.22.tgz#b034f544c1346093a235f6bba46497a1ba344fc1"
integrity sha512-2N0lSoU4GjfLSO50wvKpMQgKd4HdI2UHEhQPPPnlgfBJlOgJxkjpkYBqzk08f1gItBB6xF/n+ykso2hgxuydsA== integrity sha512-nvRaB1PyG4scn9/qNzlkwEwLzuoPH3Gjp7Q/pLuwUgOTt1oPMlnCI3A3rgkt+eZnU71emOiEv/mR201HoURPGg==
"@nodelib/fs.scandir@2.1.5": "@nodelib/fs.scandir@2.1.5":
version "2.1.5" version "2.1.5"
@ -4603,6 +4571,13 @@ binary-extensions@^2.0.0:
resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d" resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d"
integrity sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA== integrity sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==
bindings@^1.5.0:
version "1.5.0"
resolved "https://registry.yarnpkg.com/bindings/-/bindings-1.5.0.tgz#10353c9e945334bc0511a6d90b38fbc7c9c504df"
integrity sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==
dependencies:
file-uri-to-path "1.0.0"
body-scroll-lock@^3.1.5: body-scroll-lock@^3.1.5:
version "3.1.5" version "3.1.5"
resolved "https://registry.yarnpkg.com/body-scroll-lock/-/body-scroll-lock-3.1.5.tgz#c1392d9217ed2c3e237fee1e910f6cdd80b7aaec" resolved "https://registry.yarnpkg.com/body-scroll-lock/-/body-scroll-lock-3.1.5.tgz#c1392d9217ed2c3e237fee1e910f6cdd80b7aaec"
@ -4756,7 +4731,12 @@ camelcase@^6.2.0:
resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.3.0.tgz#5685b95eb209ac9c0c177467778c9c84df58ba9a" resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.3.0.tgz#5685b95eb209ac9c0c177467778c9c84df58ba9a"
integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA== integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==
caniuse-lite@^1.0.30001464, caniuse-lite@^1.0.30001503, caniuse-lite@^1.0.30001579: caniuse-lite@^1.0.30001464, caniuse-lite@^1.0.30001503:
version "1.0.30001503"
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001503.tgz#88b6ff1b2cf735f1f3361dc1a15b59f0561aa398"
integrity sha512-Sf9NiF+wZxPfzv8Z3iS0rXM1Do+iOy2Lxvib38glFX+08TCYYYGR5fRJXk4d77C4AYwhUjgYgMsMudbh2TqCKw==
caniuse-lite@^1.0.30001579:
version "1.0.30001585" version "1.0.30001585"
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001585.tgz#0b4e848d84919c783b2a41c13f7de8ce96744401" resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001585.tgz#0b4e848d84919c783b2a41c13f7de8ce96744401"
integrity sha512-yr2BWR1yLXQ8fMpdS/4ZZXpseBgE7o4g41x3a6AJOqZuOi+iE/WdJYAuZ6Y95i4Ohd2Y+9MzIWRR+uGABH4s3Q== integrity sha512-yr2BWR1yLXQ8fMpdS/4ZZXpseBgE7o4g41x3a6AJOqZuOi+iE/WdJYAuZ6Y95i4Ohd2Y+9MzIWRR+uGABH4s3Q==
@ -5103,24 +5083,25 @@ dc-polyfill@^0.1.4:
resolved "https://registry.yarnpkg.com/dc-polyfill/-/dc-polyfill-0.1.4.tgz#4118cec81a8fab9a5729c41c285c715ffa42495a" resolved "https://registry.yarnpkg.com/dc-polyfill/-/dc-polyfill-0.1.4.tgz#4118cec81a8fab9a5729c41c285c715ffa42495a"
integrity sha512-8iwEduR2jR9wWYggeaYtYZWRiUe3XZPyAQtMTL1otv8X3kfR8xUIVb4l5awHEeyDrH6Je7N324lKzMKlMMN6Yw== integrity sha512-8iwEduR2jR9wWYggeaYtYZWRiUe3XZPyAQtMTL1otv8X3kfR8xUIVb4l5awHEeyDrH6Je7N324lKzMKlMMN6Yw==
dd-trace@5.24.0: dd-trace@^5.30.0:
version "5.24.0" version "5.30.0"
resolved "https://registry.yarnpkg.com/dd-trace/-/dd-trace-5.24.0.tgz#971fcb53edec4023619642a1716e063987bf0c00" resolved "https://registry.yarnpkg.com/dd-trace/-/dd-trace-5.30.0.tgz#b81cf5f1e20822bee55bcb0dfe475578cea59faf"
integrity sha512-KJX/2ZRShuNafNaUkcWPwbIdq4bU1HQ0FrhPJWgKvljwAtNETeRhjac9nEe1fH2A9fTCGg5XCXifvK9Wr5g4xQ== integrity sha512-rKNuh/uLgGw3CjpBK5TkhSX/2ErVTO2/b+FQlgKXJSx/h7GFD8AzGEj3VKKAm1ANLLLjFqS9+ulLmFhgtxXsPg==
dependencies: dependencies:
"@datadog/native-appsec" "8.1.1" "@datadog/libdatadog" "^0.3.0"
"@datadog/native-iast-rewriter" "2.5.0" "@datadog/native-appsec" "8.3.0"
"@datadog/native-iast-taint-tracking" "3.1.0" "@datadog/native-iast-rewriter" "2.6.1"
"@datadog/native-metrics" "^2.0.0" "@datadog/native-iast-taint-tracking" "3.2.0"
"@datadog/pprof" "5.3.0" "@datadog/native-metrics" "^3.1.0"
"@datadog/pprof" "5.4.1"
"@datadog/sketches-js" "^2.1.0" "@datadog/sketches-js" "^2.1.0"
"@isaacs/ttlcache" "^1.4.1"
"@opentelemetry/api" ">=1.0.0 <1.9.0" "@opentelemetry/api" ">=1.0.0 <1.9.0"
"@opentelemetry/core" "^1.14.0" "@opentelemetry/core" "^1.14.0"
crypto-randomuuid "^1.0.0" crypto-randomuuid "^1.0.0"
dc-polyfill "^0.1.4" dc-polyfill "^0.1.4"
ignore "^5.2.4" ignore "^5.2.4"
import-in-the-middle "1.11.2" import-in-the-middle "1.11.2"
int64-buffer "^0.1.9"
istanbul-lib-coverage "3.2.0" istanbul-lib-coverage "3.2.0"
jest-docblock "^29.7.0" jest-docblock "^29.7.0"
koalas "^1.0.2" koalas "^1.0.2"
@ -5128,15 +5109,15 @@ dd-trace@5.24.0:
lodash.sortby "^4.7.0" lodash.sortby "^4.7.0"
lru-cache "^7.14.0" lru-cache "^7.14.0"
module-details-from-path "^1.0.3" module-details-from-path "^1.0.3"
msgpack-lite "^0.1.26"
opentracing ">=0.12.1" opentracing ">=0.12.1"
path-to-regexp "^0.1.10" path-to-regexp "^0.1.12"
pprof-format "^2.1.0" pprof-format "^2.1.0"
protobufjs "^7.2.5" protobufjs "^7.2.5"
retry "^0.13.1" retry "^0.13.1"
rfdc "^1.3.1" rfdc "^1.3.1"
semver "^7.5.4" semver "^7.5.4"
shell-quote "^1.8.1" shell-quote "^1.8.1"
source-map "^0.7.4"
tlhunter-sorted-set "^0.1.0" tlhunter-sorted-set "^0.1.0"
debug@4, debug@4.3.4, debug@4.x, debug@^4.1.0, debug@^4.1.1, debug@^4.3.2, debug@^4.3.3, debug@^4.3.4: debug@4, debug@4.3.4, debug@4.x, debug@^4.1.0, debug@^4.1.1, debug@^4.3.2, debug@^4.3.3, debug@^4.3.4:
@ -5529,6 +5510,14 @@ env-paths@^2.2.0:
resolved "https://registry.yarnpkg.com/env-paths/-/env-paths-2.2.1.tgz#420399d416ce1fbe9bc0a07c62fa68d67fd0f8f2" resolved "https://registry.yarnpkg.com/env-paths/-/env-paths-2.2.1.tgz#420399d416ce1fbe9bc0a07c62fa68d67fd0f8f2"
integrity sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A== integrity sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==
erlpack@0.1.4:
version "0.1.4"
resolved "https://registry.yarnpkg.com/erlpack/-/erlpack-0.1.4.tgz#018758a53206b8e9ba1f6c58a6766e3ba261a113"
integrity sha512-CJYbkEvsB5FqCCu2tLxF1eYKi28PvemC12oqzJ9oO6mDFrFO9G9G7nNJUHhiAyyL9zfXTOJx/tOcrQk+ncD65w==
dependencies:
bindings "^1.5.0"
nan "^2.15.0"
err-code@^2.0.2: err-code@^2.0.2:
version "2.0.3" version "2.0.3"
resolved "https://registry.yarnpkg.com/err-code/-/err-code-2.0.3.tgz#23c2f3b756ffdfc608d30e27c9a941024807e7f9" resolved "https://registry.yarnpkg.com/err-code/-/err-code-2.0.3.tgz#23c2f3b756ffdfc608d30e27c9a941024807e7f9"
@ -5876,11 +5865,6 @@ esutils@^2.0.2:
resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64"
integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==
event-lite@^0.1.1:
version "0.1.3"
resolved "https://registry.yarnpkg.com/event-lite/-/event-lite-0.1.3.tgz#3dfe01144e808ac46448f0c19b4ab68e403a901d"
integrity sha512-8qz9nOz5VeD2z96elrEKD2U433+L3DWdUdDkOINLGOJvx1GsMBbMn0aCeu28y8/e85A6mCigBiFlYMnTBEGlSw==
event-target-shim@^5.0.0: event-target-shim@^5.0.0:
version "5.0.1" version "5.0.1"
resolved "https://registry.yarnpkg.com/event-target-shim/-/event-target-shim-5.0.1.tgz#5d4d3ebdf9583d63a5333ce2deb7480ab2b05789" resolved "https://registry.yarnpkg.com/event-target-shim/-/event-target-shim-5.0.1.tgz#5d4d3ebdf9583d63a5333ce2deb7480ab2b05789"
@ -6041,6 +6025,11 @@ file-entry-cache@^6.0.1:
dependencies: dependencies:
flat-cache "^3.0.4" flat-cache "^3.0.4"
file-uri-to-path@1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz#553a7b8446ff6f684359c445f1e37a05dacc33dd"
integrity sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==
filelist@^1.0.4: filelist@^1.0.4:
version "1.0.4" version "1.0.4"
resolved "https://registry.yarnpkg.com/filelist/-/filelist-1.0.4.tgz#f78978a1e944775ff9e62e744424f215e58352b5" resolved "https://registry.yarnpkg.com/filelist/-/filelist-1.0.4.tgz#f78978a1e944775ff9e62e744424f215e58352b5"
@ -6746,7 +6735,7 @@ idb@7.1.1, idb@^7.0.1:
resolved "https://registry.yarnpkg.com/idb/-/idb-7.1.1.tgz#d910ded866d32c7ced9befc5bfdf36f572ced72b" resolved "https://registry.yarnpkg.com/idb/-/idb-7.1.1.tgz#d910ded866d32c7ced9befc5bfdf36f572ced72b"
integrity sha512-gchesWBzyvGHRO9W8tzUWFDycow5gwjvFKfyV9FF32Y7F50yZMp7mP+T2mJIWFx49zicqyC4uefHM17o6xKIVQ== integrity sha512-gchesWBzyvGHRO9W8tzUWFDycow5gwjvFKfyV9FF32Y7F50yZMp7mP+T2mJIWFx49zicqyC4uefHM17o6xKIVQ==
ieee754@^1.1.13, ieee754@^1.1.8: ieee754@^1.1.13:
version "1.2.1" version "1.2.1"
resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352" resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352"
integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA== integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==
@ -6839,11 +6828,6 @@ install-artifact-from-github@^1.3.3:
resolved "https://registry.yarnpkg.com/install-artifact-from-github/-/install-artifact-from-github-1.3.3.tgz#57d89bacfa0f47d7307fe41b6247cda9f9a8079c" resolved "https://registry.yarnpkg.com/install-artifact-from-github/-/install-artifact-from-github-1.3.3.tgz#57d89bacfa0f47d7307fe41b6247cda9f9a8079c"
integrity sha512-x79SL0d8WOi1ZjXSTUqqs0GPQZ92YArJAN9O46wgU9wdH2U9ecyyhB9YGDbPe2OLV4ptmt6AZYRQZ2GydQZosQ== integrity sha512-x79SL0d8WOi1ZjXSTUqqs0GPQZ92YArJAN9O46wgU9wdH2U9ecyyhB9YGDbPe2OLV4ptmt6AZYRQZ2GydQZosQ==
int64-buffer@^0.1.9:
version "0.1.10"
resolved "https://registry.yarnpkg.com/int64-buffer/-/int64-buffer-0.1.10.tgz#277b228a87d95ad777d07c13832022406a473423"
integrity sha512-v7cSY1J8ydZ0GyjUHqF+1bshJ6cnEVLo9EnjB8p+4HDRPZc9N5jjmvUV7NvEsqQOKyH0pmIBFWXVQbiS0+OBbA==
internal-slot@^1.0.3, internal-slot@^1.0.5: internal-slot@^1.0.3, internal-slot@^1.0.5:
version "1.0.5" version "1.0.5"
resolved "https://registry.yarnpkg.com/internal-slot/-/internal-slot-1.0.5.tgz#f2a2ee21f668f8627a4667f309dc0f4fb6674986" resolved "https://registry.yarnpkg.com/internal-slot/-/internal-slot-1.0.5.tgz#f2a2ee21f668f8627a4667f309dc0f4fb6674986"
@ -7116,7 +7100,7 @@ is-wsl@^2.2.0:
dependencies: dependencies:
is-docker "^2.0.0" is-docker "^2.0.0"
isarray@^1.0.0, isarray@~1.0.0: isarray@~1.0.0:
version "1.0.0" version "1.0.0"
resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11"
integrity sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ== integrity sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==
@ -8241,10 +8225,10 @@ mongodb@4.17.2:
"@aws-sdk/credential-providers" "^3.186.0" "@aws-sdk/credential-providers" "^3.186.0"
"@mongodb-js/saslprep" "^1.1.0" "@mongodb-js/saslprep" "^1.1.0"
mongoose@6.13.6: mongoose@6.13.5:
version "6.13.6" version "6.13.5"
resolved "https://registry.yarnpkg.com/mongoose/-/mongoose-6.13.6.tgz#5f90f1bfd470a30a5fcb06e88bdc3ae47fbe6dd4" resolved "https://registry.yarnpkg.com/mongoose/-/mongoose-6.13.5.tgz#33e628d259787221e8c6ecc740189896f35c7edc"
integrity sha512-1c5NBoiJ+n7wBVaifBsFVSnVkCB/m6IfnZh6ppnyQVLTtK99mS37nfW/ytnoftIcu1ITvRDgzgOj5H2fPX5ezw== integrity sha512-podJEaIF/5N2mQymkyyUzN2NeL/68MOyYjf3O0zsgCU2B2Omnhg6NhGHVavt9ZH/VxOrwKE9XphbuHDFK+T06g==
dependencies: dependencies:
bson "^4.7.2" bson "^4.7.2"
kareem "2.5.1" kareem "2.5.1"
@ -8276,16 +8260,6 @@ ms@2.1.3, ms@^2.0.0, ms@^2.1.1:
resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2"
integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==
msgpack-lite@^0.1.26:
version "0.1.26"
resolved "https://registry.yarnpkg.com/msgpack-lite/-/msgpack-lite-0.1.26.tgz#dd3c50b26f059f25e7edee3644418358e2a9ad89"
integrity sha512-SZ2IxeqZ1oRFGo0xFGbvBJWMp3yLIY9rlIJyxy8CGrwZn1f0ZK4r6jV/AM1r0FZMDUkWkglOk/eeKIL9g77Nxw==
dependencies:
event-lite "^0.1.1"
ieee754 "^1.1.8"
int64-buffer "^0.1.9"
isarray "^1.0.0"
mute-stream@0.0.8: mute-stream@0.0.8:
version "0.0.8" version "0.0.8"
resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.8.tgz#1630c42b2251ff81e2a283de96a5497ea92e5e0d" resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.8.tgz#1630c42b2251ff81e2a283de96a5497ea92e5e0d"
@ -8310,7 +8284,7 @@ mz@^2.7.0:
object-assign "^4.0.1" object-assign "^4.0.1"
thenify-all "^1.0.0" thenify-all "^1.0.0"
nan@^2.17.0: nan@^2.15.0, nan@^2.17.0:
version "2.17.0" version "2.17.0"
resolved "https://registry.yarnpkg.com/nan/-/nan-2.17.0.tgz#c0150a2368a182f033e9aa5195ec76ea41a199cb" resolved "https://registry.yarnpkg.com/nan/-/nan-2.17.0.tgz#c0150a2368a182f033e9aa5195ec76ea41a199cb"
integrity sha512-2ZTgtl0nJsO0KQCjEpxcIr5D+Yv90plTitZt9JBfQvVJDS5seMl3FOvsh3+9CoYWXf/1l5OaZzzF6nDm4cagaQ== integrity sha512-2ZTgtl0nJsO0KQCjEpxcIr5D+Yv90plTitZt9JBfQvVJDS5seMl3FOvsh3+9CoYWXf/1l5OaZzzF6nDm4cagaQ==
@ -8364,12 +8338,12 @@ next-seo@^6.1.0:
resolved "https://registry.yarnpkg.com/next-seo/-/next-seo-6.1.0.tgz#b60b06958cc77e7ed56f0a61b2d6cd0afed88ebb" resolved "https://registry.yarnpkg.com/next-seo/-/next-seo-6.1.0.tgz#b60b06958cc77e7ed56f0a61b2d6cd0afed88ebb"
integrity sha512-iMBpFoJsR5zWhguHJvsoBDxDSmdYTHtnVPB1ij+CD0NReQCP78ZxxbdL9qkKIf4oEuZEqZkrjAQLB0bkII7RYA== integrity sha512-iMBpFoJsR5zWhguHJvsoBDxDSmdYTHtnVPB1ij+CD0NReQCP78ZxxbdL9qkKIf4oEuZEqZkrjAQLB0bkII7RYA==
next@^14.2.32: next@^14.2.22:
version "14.2.32" version "14.2.22"
resolved "https://registry.yarnpkg.com/next/-/next-14.2.32.tgz#279b544f0c8ed023c33454ce4d563d3e05c2f3fb" resolved "https://registry.yarnpkg.com/next/-/next-14.2.22.tgz#0cd664916ef4c725f31fa812d870348cffd0115b"
integrity sha512-fg5g0GZ7/nFc09X8wLe6pNSU8cLWbLRG3TZzPJ1BJvi2s9m7eF991se67wliM9kR5yLHRkyGKU49MMx58s3LJg== integrity sha512-Ps2caobQ9hlEhscLPiPm3J3SYhfwfpMqzsoCMZGWxt9jBRK9hoBZj2A37i8joKhsyth2EuVKDVJCTF5/H4iEDw==
dependencies: dependencies:
"@next/env" "14.2.32" "@next/env" "14.2.22"
"@swc/helpers" "0.5.5" "@swc/helpers" "0.5.5"
busboy "1.6.0" busboy "1.6.0"
caniuse-lite "^1.0.30001579" caniuse-lite "^1.0.30001579"
@ -8377,15 +8351,15 @@ next@^14.2.32:
postcss "8.4.31" postcss "8.4.31"
styled-jsx "5.1.1" styled-jsx "5.1.1"
optionalDependencies: optionalDependencies:
"@next/swc-darwin-arm64" "14.2.32" "@next/swc-darwin-arm64" "14.2.22"
"@next/swc-darwin-x64" "14.2.32" "@next/swc-darwin-x64" "14.2.22"
"@next/swc-linux-arm64-gnu" "14.2.32" "@next/swc-linux-arm64-gnu" "14.2.22"
"@next/swc-linux-arm64-musl" "14.2.32" "@next/swc-linux-arm64-musl" "14.2.22"
"@next/swc-linux-x64-gnu" "14.2.32" "@next/swc-linux-x64-gnu" "14.2.22"
"@next/swc-linux-x64-musl" "14.2.32" "@next/swc-linux-x64-musl" "14.2.22"
"@next/swc-win32-arm64-msvc" "14.2.32" "@next/swc-win32-arm64-msvc" "14.2.22"
"@next/swc-win32-ia32-msvc" "14.2.32" "@next/swc-win32-ia32-msvc" "14.2.22"
"@next/swc-win32-x64-msvc" "14.2.32" "@next/swc-win32-x64-msvc" "14.2.22"
node-addon-api@^6.1.0: node-addon-api@^6.1.0:
version "6.1.0" version "6.1.0"
@ -8417,9 +8391,9 @@ node-fetch@^2.6.9, node-fetch@^2.7.0:
whatwg-url "^5.0.0" whatwg-url "^5.0.0"
node-forge@^1.3.1: node-forge@^1.3.1:
version "1.3.2" version "1.3.1"
resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-1.3.2.tgz#d0d2659a26eef778bf84d73e7f55c08144ee7750" resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-1.3.1.tgz#be8da2af243b2417d5f646a770663a92b7e9ded3"
integrity sha512-6xKiQ+cph9KImrRh0VsjH2d8/GXA4FIMlgU4B757iI1ApvcyA9VlouP0yZJha01V+huImO+kKMU7ih+2+E14fw== integrity sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==
node-gyp-build@<4.0, node-gyp-build@^3.9.0: node-gyp-build@<4.0, node-gyp-build@^3.9.0:
version "3.9.0" version "3.9.0"
@ -8789,7 +8763,7 @@ path-scurry@^1.7.0:
lru-cache "^9.1.1" lru-cache "^9.1.1"
minipass "^5.0.0 || ^6.0.2" minipass "^5.0.0 || ^6.0.2"
path-to-regexp@^0.1.10: path-to-regexp@^0.1.12:
version "0.1.12" version "0.1.12"
resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.12.tgz#d5e1a12e478a976d432ef3c58d534b9923164bb7" resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.12.tgz#d5e1a12e478a976d432ef3c58d534b9923164bb7"
integrity sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ== integrity sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==
@ -9546,10 +9520,10 @@ regenerate@^1.4.2:
resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.4.2.tgz#b9346d8827e8f5a32f7ba29637d398b69014848a" resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.4.2.tgz#b9346d8827e8f5a32f7ba29637d398b69014848a"
integrity sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A== integrity sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==
regenerator-runtime@^0.14.0: regenerator-runtime@^0.13.11:
version "0.14.1" version "0.13.11"
resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz#356ade10263f685dda125100cd862c1db895327f" resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz#f6dca3e7ceec20590d07ada785636a90cdca17f9"
integrity sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw== integrity sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==
regenerator-transform@^0.15.1: regenerator-transform@^0.15.1:
version "0.15.1" version "0.15.1"
@ -10733,9 +10707,9 @@ undici-types@~6.20.0:
integrity sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg== integrity sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==
undici@^5.22.1: undici@^5.22.1:
version "5.29.0" version "5.28.5"
resolved "https://registry.yarnpkg.com/undici/-/undici-5.29.0.tgz#419595449ae3f2cdcba3580a2e8903399bd1f5a3" resolved "https://registry.yarnpkg.com/undici/-/undici-5.28.5.tgz#b2b94b6bf8f1d919bc5a6f31f2c01deb02e54d4b"
integrity sha512-raqeBD6NQK4SkWhQzeYKd1KmIG6dllBOTt55Rmkt4HtI9mwdWtJljnrXjAFUBLTSN67HWrOIZ3EPF4kjUw80Bg== integrity sha512-zICwjrDrcrUE0pyyJc1I2QzBkLM8FINsgOrt6WjA+BgajVq9Nxu2PbFFXUrAggLfDXlZGZBVZYw7WNV5KiBiBA==
dependencies: dependencies:
"@fastify/busboy" "^2.0.0" "@fastify/busboy" "^2.0.0"