Merge branch 'experimental' into develop
First 4.0.0-Pudding commit of develop
This commit is contained in:
commit
3ac32871f6
55 changed files with 2321 additions and 1696 deletions
5
.gitignore
vendored
5
.gitignore
vendored
|
@ -79,6 +79,7 @@ web_modules/
|
|||
.env.test.local
|
||||
.env.production.local
|
||||
.env.local
|
||||
docker.env
|
||||
|
||||
# parcel-bundler cache (https://parceljs.org/)
|
||||
.cache
|
||||
|
@ -138,3 +139,7 @@ db/
|
|||
.idea/
|
||||
./database/
|
||||
.DS_Store
|
||||
|
||||
# Prisma
|
||||
prisma/**/*.*
|
||||
!prisma/schema.prisma
|
||||
|
|
4
.vscode/extensions.json
vendored
4
.vscode/extensions.json
vendored
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"recommendations": [
|
||||
"arcanis.vscode-zipfs",
|
||||
"esbenp.prettier-vscode",
|
||||
"dbaeumer.vscode-eslint"
|
||||
"dbaeumer.vscode-eslint",
|
||||
"esbenp.prettier-vscode"
|
||||
]
|
||||
}
|
||||
|
|
4
.vscode/settings.json
vendored
4
.vscode/settings.json
vendored
|
@ -3,8 +3,8 @@
|
|||
"**/.yarn": true,
|
||||
"**/.pnp.*": true
|
||||
},
|
||||
"eslint.nodePath": ".yarn/sdks",
|
||||
"prettier.prettierPath": ".yarn/sdks/prettier/index.cjs",
|
||||
"typescript.tsdk": ".yarn/sdks/typescript/lib",
|
||||
"typescript.enablePromptUseWorkspaceTsdk": true,
|
||||
"eslint.nodePath": ".yarn/sdks"
|
||||
"typescript.enablePromptUseWorkspaceTsdk": true
|
||||
}
|
||||
|
|
894
.yarn/releases/yarn-4.3.1.cjs
vendored
894
.yarn/releases/yarn-4.3.1.cjs
vendored
File diff suppressed because one or more lines are too long
925
.yarn/releases/yarn-4.5.0.cjs
vendored
Normal file
925
.yarn/releases/yarn-4.5.0.cjs
vendored
Normal file
File diff suppressed because one or more lines are too long
7
.yarn/sdks/eslint/bin/eslint.js
vendored
7
.yarn/sdks/eslint/bin/eslint.js
vendored
|
@ -8,6 +8,7 @@ const {pathToFileURL} = require(`url`);
|
|||
const relPnpApiPath = "../../../../.pnp.cjs";
|
||||
|
||||
const absPnpApiPath = resolve(__dirname, relPnpApiPath);
|
||||
const absUserWrapperPath = resolve(__dirname, `./sdk.user.cjs`);
|
||||
const absRequire = createRequire(absPnpApiPath);
|
||||
|
||||
const absPnpLoaderPath = resolve(absPnpApiPath, `../.pnp.loader.mjs`);
|
||||
|
@ -23,5 +24,9 @@ if (existsSync(absPnpApiPath)) {
|
|||
}
|
||||
}
|
||||
|
||||
const wrapWithUserWrapper = existsSync(absUserWrapperPath)
|
||||
? exports => absRequire(absUserWrapperPath)(exports)
|
||||
: exports => exports;
|
||||
|
||||
// Defer to the real eslint/bin/eslint.js your application uses
|
||||
module.exports = absRequire(`eslint/bin/eslint.js`);
|
||||
module.exports = wrapWithUserWrapper(absRequire(`eslint/bin/eslint.js`));
|
||||
|
|
7
.yarn/sdks/eslint/lib/api.js
vendored
7
.yarn/sdks/eslint/lib/api.js
vendored
|
@ -8,6 +8,7 @@ const {pathToFileURL} = require(`url`);
|
|||
const relPnpApiPath = "../../../../.pnp.cjs";
|
||||
|
||||
const absPnpApiPath = resolve(__dirname, relPnpApiPath);
|
||||
const absUserWrapperPath = resolve(__dirname, `./sdk.user.cjs`);
|
||||
const absRequire = createRequire(absPnpApiPath);
|
||||
|
||||
const absPnpLoaderPath = resolve(absPnpApiPath, `../.pnp.loader.mjs`);
|
||||
|
@ -23,5 +24,9 @@ if (existsSync(absPnpApiPath)) {
|
|||
}
|
||||
}
|
||||
|
||||
const wrapWithUserWrapper = existsSync(absUserWrapperPath)
|
||||
? exports => absRequire(absUserWrapperPath)(exports)
|
||||
: exports => exports;
|
||||
|
||||
// Defer to the real eslint your application uses
|
||||
module.exports = absRequire(`eslint`);
|
||||
module.exports = wrapWithUserWrapper(absRequire(`eslint`));
|
||||
|
|
32
.yarn/sdks/eslint/lib/types/index.d.ts
vendored
Normal file
32
.yarn/sdks/eslint/lib/types/index.d.ts
vendored
Normal file
|
@ -0,0 +1,32 @@
|
|||
#!/usr/bin/env node
|
||||
|
||||
const {existsSync} = require(`fs`);
|
||||
const {createRequire, register} = require(`module`);
|
||||
const {resolve} = require(`path`);
|
||||
const {pathToFileURL} = require(`url`);
|
||||
|
||||
const relPnpApiPath = "../../../../../.pnp.cjs";
|
||||
|
||||
const absPnpApiPath = resolve(__dirname, relPnpApiPath);
|
||||
const absUserWrapperPath = resolve(__dirname, `./sdk.user.cjs`);
|
||||
const absRequire = createRequire(absPnpApiPath);
|
||||
|
||||
const absPnpLoaderPath = resolve(absPnpApiPath, `../.pnp.loader.mjs`);
|
||||
const isPnpLoaderEnabled = existsSync(absPnpLoaderPath);
|
||||
|
||||
if (existsSync(absPnpApiPath)) {
|
||||
if (!process.versions.pnp) {
|
||||
// Setup the environment to be able to require eslint
|
||||
require(absPnpApiPath).setup();
|
||||
if (isPnpLoaderEnabled && register) {
|
||||
register(pathToFileURL(absPnpLoaderPath));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const wrapWithUserWrapper = existsSync(absUserWrapperPath)
|
||||
? exports => absRequire(absUserWrapperPath)(exports)
|
||||
: exports => exports;
|
||||
|
||||
// Defer to the real eslint your application uses
|
||||
module.exports = wrapWithUserWrapper(absRequire(`eslint`));
|
32
.yarn/sdks/eslint/lib/types/rules/index.d.ts
vendored
Normal file
32
.yarn/sdks/eslint/lib/types/rules/index.d.ts
vendored
Normal file
|
@ -0,0 +1,32 @@
|
|||
#!/usr/bin/env node
|
||||
|
||||
const {existsSync} = require(`fs`);
|
||||
const {createRequire, register} = require(`module`);
|
||||
const {resolve} = require(`path`);
|
||||
const {pathToFileURL} = require(`url`);
|
||||
|
||||
const relPnpApiPath = "../../../../../../.pnp.cjs";
|
||||
|
||||
const absPnpApiPath = resolve(__dirname, relPnpApiPath);
|
||||
const absUserWrapperPath = resolve(__dirname, `./sdk.user.cjs`);
|
||||
const absRequire = createRequire(absPnpApiPath);
|
||||
|
||||
const absPnpLoaderPath = resolve(absPnpApiPath, `../.pnp.loader.mjs`);
|
||||
const isPnpLoaderEnabled = existsSync(absPnpLoaderPath);
|
||||
|
||||
if (existsSync(absPnpApiPath)) {
|
||||
if (!process.versions.pnp) {
|
||||
// Setup the environment to be able to require eslint/rules
|
||||
require(absPnpApiPath).setup();
|
||||
if (isPnpLoaderEnabled && register) {
|
||||
register(pathToFileURL(absPnpLoaderPath));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const wrapWithUserWrapper = existsSync(absUserWrapperPath)
|
||||
? exports => absRequire(absUserWrapperPath)(exports)
|
||||
: exports => exports;
|
||||
|
||||
// Defer to the real eslint/rules your application uses
|
||||
module.exports = wrapWithUserWrapper(absRequire(`eslint/rules`));
|
32
.yarn/sdks/eslint/lib/types/universal.d.ts
vendored
Normal file
32
.yarn/sdks/eslint/lib/types/universal.d.ts
vendored
Normal file
|
@ -0,0 +1,32 @@
|
|||
#!/usr/bin/env node
|
||||
|
||||
const {existsSync} = require(`fs`);
|
||||
const {createRequire, register} = require(`module`);
|
||||
const {resolve} = require(`path`);
|
||||
const {pathToFileURL} = require(`url`);
|
||||
|
||||
const relPnpApiPath = "../../../../../.pnp.cjs";
|
||||
|
||||
const absPnpApiPath = resolve(__dirname, relPnpApiPath);
|
||||
const absUserWrapperPath = resolve(__dirname, `./sdk.user.cjs`);
|
||||
const absRequire = createRequire(absPnpApiPath);
|
||||
|
||||
const absPnpLoaderPath = resolve(absPnpApiPath, `../.pnp.loader.mjs`);
|
||||
const isPnpLoaderEnabled = existsSync(absPnpLoaderPath);
|
||||
|
||||
if (existsSync(absPnpApiPath)) {
|
||||
if (!process.versions.pnp) {
|
||||
// Setup the environment to be able to require eslint/universal
|
||||
require(absPnpApiPath).setup();
|
||||
if (isPnpLoaderEnabled && register) {
|
||||
register(pathToFileURL(absPnpLoaderPath));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const wrapWithUserWrapper = existsSync(absUserWrapperPath)
|
||||
? exports => absRequire(absUserWrapperPath)(exports)
|
||||
: exports => exports;
|
||||
|
||||
// Defer to the real eslint/universal your application uses
|
||||
module.exports = wrapWithUserWrapper(absRequire(`eslint/universal`));
|
32
.yarn/sdks/eslint/lib/types/use-at-your-own-risk.d.ts
vendored
Normal file
32
.yarn/sdks/eslint/lib/types/use-at-your-own-risk.d.ts
vendored
Normal file
|
@ -0,0 +1,32 @@
|
|||
#!/usr/bin/env node
|
||||
|
||||
const {existsSync} = require(`fs`);
|
||||
const {createRequire, register} = require(`module`);
|
||||
const {resolve} = require(`path`);
|
||||
const {pathToFileURL} = require(`url`);
|
||||
|
||||
const relPnpApiPath = "../../../../../.pnp.cjs";
|
||||
|
||||
const absPnpApiPath = resolve(__dirname, relPnpApiPath);
|
||||
const absUserWrapperPath = resolve(__dirname, `./sdk.user.cjs`);
|
||||
const absRequire = createRequire(absPnpApiPath);
|
||||
|
||||
const absPnpLoaderPath = resolve(absPnpApiPath, `../.pnp.loader.mjs`);
|
||||
const isPnpLoaderEnabled = existsSync(absPnpLoaderPath);
|
||||
|
||||
if (existsSync(absPnpApiPath)) {
|
||||
if (!process.versions.pnp) {
|
||||
// Setup the environment to be able to require eslint/use-at-your-own-risk
|
||||
require(absPnpApiPath).setup();
|
||||
if (isPnpLoaderEnabled && register) {
|
||||
register(pathToFileURL(absPnpLoaderPath));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const wrapWithUserWrapper = existsSync(absUserWrapperPath)
|
||||
? exports => absRequire(absUserWrapperPath)(exports)
|
||||
: exports => exports;
|
||||
|
||||
// Defer to the real eslint/use-at-your-own-risk your application uses
|
||||
module.exports = wrapWithUserWrapper(absRequire(`eslint/use-at-your-own-risk`));
|
32
.yarn/sdks/eslint/lib/universal.js
vendored
Normal file
32
.yarn/sdks/eslint/lib/universal.js
vendored
Normal file
|
@ -0,0 +1,32 @@
|
|||
#!/usr/bin/env node
|
||||
|
||||
const {existsSync} = require(`fs`);
|
||||
const {createRequire, register} = require(`module`);
|
||||
const {resolve} = require(`path`);
|
||||
const {pathToFileURL} = require(`url`);
|
||||
|
||||
const relPnpApiPath = "../../../../.pnp.cjs";
|
||||
|
||||
const absPnpApiPath = resolve(__dirname, relPnpApiPath);
|
||||
const absUserWrapperPath = resolve(__dirname, `./sdk.user.cjs`);
|
||||
const absRequire = createRequire(absPnpApiPath);
|
||||
|
||||
const absPnpLoaderPath = resolve(absPnpApiPath, `../.pnp.loader.mjs`);
|
||||
const isPnpLoaderEnabled = existsSync(absPnpLoaderPath);
|
||||
|
||||
if (existsSync(absPnpApiPath)) {
|
||||
if (!process.versions.pnp) {
|
||||
// Setup the environment to be able to require eslint/universal
|
||||
require(absPnpApiPath).setup();
|
||||
if (isPnpLoaderEnabled && register) {
|
||||
register(pathToFileURL(absPnpLoaderPath));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const wrapWithUserWrapper = existsSync(absUserWrapperPath)
|
||||
? exports => absRequire(absUserWrapperPath)(exports)
|
||||
: exports => exports;
|
||||
|
||||
// Defer to the real eslint/universal your application uses
|
||||
module.exports = wrapWithUserWrapper(absRequire(`eslint/universal`));
|
7
.yarn/sdks/eslint/lib/unsupported-api.js
vendored
7
.yarn/sdks/eslint/lib/unsupported-api.js
vendored
|
@ -8,6 +8,7 @@ const {pathToFileURL} = require(`url`);
|
|||
const relPnpApiPath = "../../../../.pnp.cjs";
|
||||
|
||||
const absPnpApiPath = resolve(__dirname, relPnpApiPath);
|
||||
const absUserWrapperPath = resolve(__dirname, `./sdk.user.cjs`);
|
||||
const absRequire = createRequire(absPnpApiPath);
|
||||
|
||||
const absPnpLoaderPath = resolve(absPnpApiPath, `../.pnp.loader.mjs`);
|
||||
|
@ -23,5 +24,9 @@ if (existsSync(absPnpApiPath)) {
|
|||
}
|
||||
}
|
||||
|
||||
const wrapWithUserWrapper = existsSync(absUserWrapperPath)
|
||||
? exports => absRequire(absUserWrapperPath)(exports)
|
||||
: exports => exports;
|
||||
|
||||
// Defer to the real eslint/use-at-your-own-risk your application uses
|
||||
module.exports = absRequire(`eslint/use-at-your-own-risk`);
|
||||
module.exports = wrapWithUserWrapper(absRequire(`eslint/use-at-your-own-risk`));
|
||||
|
|
19
.yarn/sdks/eslint/package.json
vendored
19
.yarn/sdks/eslint/package.json
vendored
|
@ -1,14 +1,27 @@
|
|||
{
|
||||
"name": "eslint",
|
||||
"version": "9.5.0-sdk",
|
||||
"version": "9.11.0-sdk",
|
||||
"main": "./lib/api.js",
|
||||
"type": "commonjs",
|
||||
"bin": {
|
||||
"eslint": "./bin/eslint.js"
|
||||
},
|
||||
"exports": {
|
||||
".": {
|
||||
"types": "./lib/types/index.d.ts",
|
||||
"default": "./lib/api.js"
|
||||
},
|
||||
"./package.json": "./package.json",
|
||||
".": "./lib/api.js",
|
||||
"./use-at-your-own-risk": "./lib/unsupported-api.js"
|
||||
"./use-at-your-own-risk": {
|
||||
"types": "./lib/types/use-at-your-own-risk.d.ts",
|
||||
"default": "./lib/unsupported-api.js"
|
||||
},
|
||||
"./rules": {
|
||||
"types": "./lib/types/rules/index.d.ts"
|
||||
},
|
||||
"./universal": {
|
||||
"types": "./lib/types/universal.d.ts",
|
||||
"default": "./lib/universal.js"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
7
.yarn/sdks/prettier/bin/prettier.cjs
vendored
7
.yarn/sdks/prettier/bin/prettier.cjs
vendored
|
@ -8,6 +8,7 @@ const {pathToFileURL} = require(`url`);
|
|||
const relPnpApiPath = "../../../../.pnp.cjs";
|
||||
|
||||
const absPnpApiPath = resolve(__dirname, relPnpApiPath);
|
||||
const absUserWrapperPath = resolve(__dirname, `./sdk.user.cjs`);
|
||||
const absRequire = createRequire(absPnpApiPath);
|
||||
|
||||
const absPnpLoaderPath = resolve(absPnpApiPath, `../.pnp.loader.mjs`);
|
||||
|
@ -23,5 +24,9 @@ if (existsSync(absPnpApiPath)) {
|
|||
}
|
||||
}
|
||||
|
||||
const wrapWithUserWrapper = existsSync(absUserWrapperPath)
|
||||
? exports => absRequire(absUserWrapperPath)(exports)
|
||||
: exports => exports;
|
||||
|
||||
// Defer to the real prettier/bin/prettier.cjs your application uses
|
||||
module.exports = absRequire(`prettier/bin/prettier.cjs`);
|
||||
module.exports = wrapWithUserWrapper(absRequire(`prettier/bin/prettier.cjs`));
|
||||
|
|
7
.yarn/sdks/prettier/index.cjs
vendored
7
.yarn/sdks/prettier/index.cjs
vendored
|
@ -8,6 +8,7 @@ const {pathToFileURL} = require(`url`);
|
|||
const relPnpApiPath = "../../../.pnp.cjs";
|
||||
|
||||
const absPnpApiPath = resolve(__dirname, relPnpApiPath);
|
||||
const absUserWrapperPath = resolve(__dirname, `./sdk.user.cjs`);
|
||||
const absRequire = createRequire(absPnpApiPath);
|
||||
|
||||
const absPnpLoaderPath = resolve(absPnpApiPath, `../.pnp.loader.mjs`);
|
||||
|
@ -23,5 +24,9 @@ if (existsSync(absPnpApiPath)) {
|
|||
}
|
||||
}
|
||||
|
||||
const wrapWithUserWrapper = existsSync(absUserWrapperPath)
|
||||
? exports => absRequire(absUserWrapperPath)(exports)
|
||||
: exports => exports;
|
||||
|
||||
// Defer to the real prettier your application uses
|
||||
module.exports = absRequire(`prettier`);
|
||||
module.exports = wrapWithUserWrapper(absRequire(`prettier`));
|
||||
|
|
2
.yarn/sdks/prettier/package.json
vendored
2
.yarn/sdks/prettier/package.json
vendored
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "prettier",
|
||||
"version": "3.3.2-sdk",
|
||||
"version": "3.3.3-sdk",
|
||||
"main": "./index.cjs",
|
||||
"type": "commonjs",
|
||||
"bin": "./bin/prettier.cjs"
|
||||
|
|
7
.yarn/sdks/typescript/bin/tsc
vendored
7
.yarn/sdks/typescript/bin/tsc
vendored
|
@ -8,6 +8,7 @@ const {pathToFileURL} = require(`url`);
|
|||
const relPnpApiPath = "../../../../.pnp.cjs";
|
||||
|
||||
const absPnpApiPath = resolve(__dirname, relPnpApiPath);
|
||||
const absUserWrapperPath = resolve(__dirname, `./sdk.user.cjs`);
|
||||
const absRequire = createRequire(absPnpApiPath);
|
||||
|
||||
const absPnpLoaderPath = resolve(absPnpApiPath, `../.pnp.loader.mjs`);
|
||||
|
@ -23,5 +24,9 @@ if (existsSync(absPnpApiPath)) {
|
|||
}
|
||||
}
|
||||
|
||||
const wrapWithUserWrapper = existsSync(absUserWrapperPath)
|
||||
? exports => absRequire(absUserWrapperPath)(exports)
|
||||
: exports => exports;
|
||||
|
||||
// Defer to the real typescript/bin/tsc your application uses
|
||||
module.exports = absRequire(`typescript/bin/tsc`);
|
||||
module.exports = wrapWithUserWrapper(absRequire(`typescript/bin/tsc`));
|
||||
|
|
7
.yarn/sdks/typescript/bin/tsserver
vendored
7
.yarn/sdks/typescript/bin/tsserver
vendored
|
@ -8,6 +8,7 @@ const {pathToFileURL} = require(`url`);
|
|||
const relPnpApiPath = "../../../../.pnp.cjs";
|
||||
|
||||
const absPnpApiPath = resolve(__dirname, relPnpApiPath);
|
||||
const absUserWrapperPath = resolve(__dirname, `./sdk.user.cjs`);
|
||||
const absRequire = createRequire(absPnpApiPath);
|
||||
|
||||
const absPnpLoaderPath = resolve(absPnpApiPath, `../.pnp.loader.mjs`);
|
||||
|
@ -23,5 +24,9 @@ if (existsSync(absPnpApiPath)) {
|
|||
}
|
||||
}
|
||||
|
||||
const wrapWithUserWrapper = existsSync(absUserWrapperPath)
|
||||
? exports => absRequire(absUserWrapperPath)(exports)
|
||||
: exports => exports;
|
||||
|
||||
// Defer to the real typescript/bin/tsserver your application uses
|
||||
module.exports = absRequire(`typescript/bin/tsserver`);
|
||||
module.exports = wrapWithUserWrapper(absRequire(`typescript/bin/tsserver`));
|
||||
|
|
7
.yarn/sdks/typescript/lib/tsc.js
vendored
7
.yarn/sdks/typescript/lib/tsc.js
vendored
|
@ -8,6 +8,7 @@ const {pathToFileURL} = require(`url`);
|
|||
const relPnpApiPath = "../../../../.pnp.cjs";
|
||||
|
||||
const absPnpApiPath = resolve(__dirname, relPnpApiPath);
|
||||
const absUserWrapperPath = resolve(__dirname, `./sdk.user.cjs`);
|
||||
const absRequire = createRequire(absPnpApiPath);
|
||||
|
||||
const absPnpLoaderPath = resolve(absPnpApiPath, `../.pnp.loader.mjs`);
|
||||
|
@ -23,5 +24,9 @@ if (existsSync(absPnpApiPath)) {
|
|||
}
|
||||
}
|
||||
|
||||
const wrapWithUserWrapper = existsSync(absUserWrapperPath)
|
||||
? exports => absRequire(absUserWrapperPath)(exports)
|
||||
: exports => exports;
|
||||
|
||||
// Defer to the real typescript/lib/tsc.js your application uses
|
||||
module.exports = absRequire(`typescript/lib/tsc.js`);
|
||||
module.exports = wrapWithUserWrapper(absRequire(`typescript/lib/tsc.js`));
|
||||
|
|
11
.yarn/sdks/typescript/lib/tsserver.js
vendored
11
.yarn/sdks/typescript/lib/tsserver.js
vendored
|
@ -8,6 +8,7 @@ const {pathToFileURL} = require(`url`);
|
|||
const relPnpApiPath = "../../../../.pnp.cjs";
|
||||
|
||||
const absPnpApiPath = resolve(__dirname, relPnpApiPath);
|
||||
const absUserWrapperPath = resolve(__dirname, `./sdk.user.cjs`);
|
||||
const absRequire = createRequire(absPnpApiPath);
|
||||
|
||||
const absPnpLoaderPath = resolve(absPnpApiPath, `../.pnp.loader.mjs`);
|
||||
|
@ -23,7 +24,15 @@ if (existsSync(absPnpApiPath)) {
|
|||
}
|
||||
}
|
||||
|
||||
const moduleWrapper = tsserver => {
|
||||
const wrapWithUserWrapper = existsSync(absUserWrapperPath)
|
||||
? exports => absRequire(absUserWrapperPath)(exports)
|
||||
: exports => exports;
|
||||
|
||||
const moduleWrapper = exports => {
|
||||
return wrapWithUserWrapper(moduleWrapperFn(exports));
|
||||
};
|
||||
|
||||
const moduleWrapperFn = tsserver => {
|
||||
if (!process.versions.pnp) {
|
||||
return tsserver;
|
||||
}
|
||||
|
|
11
.yarn/sdks/typescript/lib/tsserverlibrary.js
vendored
11
.yarn/sdks/typescript/lib/tsserverlibrary.js
vendored
|
@ -8,6 +8,7 @@ const {pathToFileURL} = require(`url`);
|
|||
const relPnpApiPath = "../../../../.pnp.cjs";
|
||||
|
||||
const absPnpApiPath = resolve(__dirname, relPnpApiPath);
|
||||
const absUserWrapperPath = resolve(__dirname, `./sdk.user.cjs`);
|
||||
const absRequire = createRequire(absPnpApiPath);
|
||||
|
||||
const absPnpLoaderPath = resolve(absPnpApiPath, `../.pnp.loader.mjs`);
|
||||
|
@ -23,7 +24,15 @@ if (existsSync(absPnpApiPath)) {
|
|||
}
|
||||
}
|
||||
|
||||
const moduleWrapper = tsserver => {
|
||||
const wrapWithUserWrapper = existsSync(absUserWrapperPath)
|
||||
? exports => absRequire(absUserWrapperPath)(exports)
|
||||
: exports => exports;
|
||||
|
||||
const moduleWrapper = exports => {
|
||||
return wrapWithUserWrapper(moduleWrapperFn(exports));
|
||||
};
|
||||
|
||||
const moduleWrapperFn = tsserver => {
|
||||
if (!process.versions.pnp) {
|
||||
return tsserver;
|
||||
}
|
||||
|
|
7
.yarn/sdks/typescript/lib/typescript.js
vendored
7
.yarn/sdks/typescript/lib/typescript.js
vendored
|
@ -8,6 +8,7 @@ const {pathToFileURL} = require(`url`);
|
|||
const relPnpApiPath = "../../../../.pnp.cjs";
|
||||
|
||||
const absPnpApiPath = resolve(__dirname, relPnpApiPath);
|
||||
const absUserWrapperPath = resolve(__dirname, `./sdk.user.cjs`);
|
||||
const absRequire = createRequire(absPnpApiPath);
|
||||
|
||||
const absPnpLoaderPath = resolve(absPnpApiPath, `../.pnp.loader.mjs`);
|
||||
|
@ -23,5 +24,9 @@ if (existsSync(absPnpApiPath)) {
|
|||
}
|
||||
}
|
||||
|
||||
const wrapWithUserWrapper = existsSync(absUserWrapperPath)
|
||||
? exports => absRequire(absUserWrapperPath)(exports)
|
||||
: exports => exports;
|
||||
|
||||
// Defer to the real typescript your application uses
|
||||
module.exports = absRequire(`typescript`);
|
||||
module.exports = wrapWithUserWrapper(absRequire(`typescript`));
|
||||
|
|
2
.yarn/sdks/typescript/package.json
vendored
2
.yarn/sdks/typescript/package.json
vendored
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "typescript",
|
||||
"version": "5.5.2-sdk",
|
||||
"version": "5.6.2-sdk",
|
||||
"main": "./lib/typescript.js",
|
||||
"type": "commonjs",
|
||||
"bin": {
|
||||
|
|
|
@ -1 +1 @@
|
|||
yarnPath: .yarn/releases/yarn-4.3.1.cjs
|
||||
yarnPath: .yarn/releases/yarn-4.5.0.cjs
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
FROM node:18.20.3
|
||||
FROM node:18.20.4
|
||||
|
||||
ENV DOCKERIZE_VERSION v0.2.0
|
||||
RUN wget https://github.com/jwilder/dockerize/releases/download/$DOCKERIZE_VERSION/dockerize-linux-amd64-$DOCKERIZE_VERSION.tar.gz \
|
||||
|
@ -8,6 +8,7 @@ RUN mkdir app
|
|||
WORKDIR /app
|
||||
COPY . .
|
||||
RUN yarn install
|
||||
RUN yarn db:push
|
||||
RUN yarn build
|
||||
|
||||
|
||||
|
|
24
README.md
24
README.md
|
@ -7,7 +7,7 @@
|
|||
### 종속성
|
||||
|
||||
- 이 프로젝트는 Node.JS을 사용하고, 패키지 매니저를 Yarn Berry로 사용합니다.
|
||||
- 이 프로젝트는 MariaDB(또는 MySQL)를 사용합니다.
|
||||
- 이 프로젝트는 MariaDB(또는 MySQL)와 Database ORM인 Prisma를 사용합니다.
|
||||
|
||||
#### 종속성 설치
|
||||
|
||||
|
@ -17,11 +17,25 @@ yarn install
|
|||
|
||||
### 설정 파일
|
||||
|
||||
- 이 프로젝트는 설정파일을 프로젝트 루트에 있는 `config.json`으로 하며, 그 내용은 `config.example.json`에서 확인할 수 있습니다.
|
||||
- 이 프로젝트는 설정파일을 프로젝트 루트에 있는 `.env`으로 하며, 그 내용은 `example.env`에서 확인할 수 있습니다.
|
||||
|
||||
#### Docker 설정
|
||||
|
||||
- Docker로 실행할 경우, 해당 설정 파일을 `docker.env`으로 하며, 그 내용은 `example-docker.env`에서 확인할 수 있습니다.
|
||||
|
||||
### prisma 설정
|
||||
|
||||
- 해당 프로젝트는 Database ORM인 Prisma를 사용하여 해당 설정이 필요합니다.
|
||||
|
||||
1. 먼저 .env에 DATABASE_URL부분을 채워 줍니다.
|
||||
|
||||
- 예시: `mysql://username:user_password@hostname:port/database?schema=public`
|
||||
|
||||
2. 터미널 에서 `yarn db:push`를 합니다.
|
||||
|
||||
### 실행
|
||||
|
||||
위 두 과정을 정상적으로 따랐다면, 아래의 명령어로 봇을 실행할 수 있습니다.
|
||||
위 과정들을 정상적으로 따랐다면, 아래의 명령어로 봇을 실행할 수 있습니다.
|
||||
|
||||
#### 그냥 실행 (디버그용 로그 출력)
|
||||
|
||||
|
@ -29,7 +43,9 @@ yarn install
|
|||
yarn dev
|
||||
```
|
||||
|
||||
#### 빌드
|
||||
#### 빌드 후 실행
|
||||
|
||||
##### 빌드
|
||||
|
||||
```sh
|
||||
yarn build
|
||||
|
|
|
@ -1,17 +0,0 @@
|
|||
{
|
||||
"bot": {
|
||||
"owner_ID": "",
|
||||
"token": "",
|
||||
"prefix": ""
|
||||
},
|
||||
"train": {
|
||||
"user_ID": ""
|
||||
},
|
||||
"mysql": {
|
||||
"user": "",
|
||||
"host": "",
|
||||
"password": "",
|
||||
"database": "",
|
||||
"port": 3306
|
||||
}
|
||||
}
|
|
@ -9,7 +9,7 @@ services:
|
|||
ports:
|
||||
- "1502:3306"
|
||||
env_file:
|
||||
- "./.env"
|
||||
- "./docker.env"
|
||||
networks:
|
||||
- muffin_ai
|
||||
discord_bot:
|
||||
|
@ -19,6 +19,8 @@ services:
|
|||
- muffin_ai
|
||||
depends_on:
|
||||
- database
|
||||
env_file:
|
||||
- "./.env"
|
||||
|
||||
networks:
|
||||
muffin_ai:
|
||||
|
|
5
example-docker.env
Normal file
5
example-docker.env
Normal file
|
@ -0,0 +1,5 @@
|
|||
# Docker configs (MariaDB container)
|
||||
MYSQL_USER=
|
||||
MYSQL_PASSWORD=
|
||||
MYSQL_DATABASE=
|
||||
MYSQL_ROOT_PASSWORD=
|
17
example.env
17
example.env
|
@ -1,4 +1,13 @@
|
|||
MYSQL_USER=
|
||||
MYSQL_PASSWORD=
|
||||
MYSQL_DATABASE=
|
||||
MYSQL_ROOT_PASSWORD=
|
||||
# Prisma configs
|
||||
# Environment variables declared in this file are automatically made available to Prisma.
|
||||
# See the documentation for more detail: https://pris.ly/d/prisma-schema#accessing-environment-variables-from-the-schema
|
||||
|
||||
# Prisma supports the native connection string format for PostgreSQL, MySQL, SQLite, SQL Server, MongoDB and CockroachDB.
|
||||
# See the documentation for all the connection string options: https://pris.ly/d/connection-strings
|
||||
DATABASE_URL=
|
||||
|
||||
# Bot configs
|
||||
BOT_TOKEN=
|
||||
BOT_OWNER_ID=
|
||||
BOT_PREFIX=
|
||||
TRAIN_USER_ID=
|
||||
|
|
40
package.json
40
package.json
|
@ -1,46 +1,52 @@
|
|||
{
|
||||
"name": "muffinbot",
|
||||
"version": "3.1.0-cake.d240925a",
|
||||
"version": "4.0.0-pudding.d240928a",
|
||||
"main": "dist/index.js",
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
"@prisma/client": "^5.19.1",
|
||||
"@sapphire/decorators": "^6.1.0",
|
||||
"@sapphire/discord.js-utilities": "^7.3.0",
|
||||
"@sapphire/framework": "^5.2.1",
|
||||
"@sapphire/pieces": "^4.3.1",
|
||||
"@sapphire/utilities": "^3.17.0",
|
||||
"discord-api-types": "^0.37.93",
|
||||
"discord.js": "^14.15.3",
|
||||
"discord-api-types": "^0.37.100",
|
||||
"discord.js": "^14.16.2",
|
||||
"dokdo": "^0.6.2",
|
||||
"mysql2": "^3.11.0",
|
||||
"semver": "^7.6.3"
|
||||
"dotenv": "^16.4.5",
|
||||
"mysql2": "^3.11.3",
|
||||
"semver": "^7.6.3",
|
||||
"undici": "^6.19.8"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@eslint/eslintrc": "^3.1.0",
|
||||
"@eslint/js": "^9.8.0",
|
||||
"@eslint/js": "^9.11.0",
|
||||
"@migan/prettier-config": "^1.2.0",
|
||||
"@types/node": "^20.14.12",
|
||||
"@types/semver": "^7",
|
||||
"@typescript-eslint/eslint-plugin": "^7.17.0",
|
||||
"@typescript-eslint/parser": "^7.17.0",
|
||||
"@types/node": "^22.5.5",
|
||||
"@types/semver": "^7.5.8",
|
||||
"@typescript-eslint/eslint-plugin": "^8.6.0",
|
||||
"@typescript-eslint/parser": "^8.6.0",
|
||||
"@yarnpkg/pnpify": "^4.1.2",
|
||||
"cross-env": "^7.0.3",
|
||||
"eslint": "^9.8.0",
|
||||
"eslint": "^9.11.0",
|
||||
"eslint-config-prettier": "^9.1.0",
|
||||
"eslint-plugin-prettier": "^5.2.1",
|
||||
"globals": "^15.8.0",
|
||||
"globals": "^15.9.0",
|
||||
"prettier": "^3.3.3",
|
||||
"ts-node": "^10.9.2",
|
||||
"tsup": "^8.2.3",
|
||||
"typescript": "^5.5.4"
|
||||
"prisma": "^5.19.1",
|
||||
"tsup": "^8.3.0",
|
||||
"typescript": "^5.6.2"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "tsup",
|
||||
"dev": "cross-env NODE_ENV=development tsup --watch --onSuccess \"node --enable-source-maps dist\"",
|
||||
"start": "cross-env NODE_ENV=production node dist"
|
||||
"start": "cross-env NODE_ENV=production node dist",
|
||||
"db:pull": "pnpify prisma db pull",
|
||||
"db:push": "pnpify prisma db push"
|
||||
},
|
||||
"resolutions": {
|
||||
"@types/ws": "^8.5.11",
|
||||
"ws": "8.18.0"
|
||||
},
|
||||
"packageManager": "yarn@4.3.1"
|
||||
"packageManager": "yarn@4.5.0"
|
||||
}
|
||||
|
|
35
prisma/schema.prisma
Normal file
35
prisma/schema.prisma
Normal file
|
@ -0,0 +1,35 @@
|
|||
generator client {
|
||||
provider = "prisma-client-js"
|
||||
output = "./"
|
||||
}
|
||||
|
||||
datasource db {
|
||||
provider = "mysql"
|
||||
url = env("DATABASE_URL")
|
||||
}
|
||||
|
||||
model learn {
|
||||
id Int @id @default(autoincrement())
|
||||
command String @db.VarChar(255)
|
||||
result String @db.VarChar(255)
|
||||
user_id String @db.VarChar(255)
|
||||
created_at DateTime @default(now()) @db.DateTime(0)
|
||||
}
|
||||
|
||||
model nsfw_content {
|
||||
id Int @id @default(autoincrement())
|
||||
text String @default("") @db.VarChar(255)
|
||||
created_at DateTime? @default(now()) @db.DateTime(0)
|
||||
persona String @default("") @db.VarChar(50)
|
||||
}
|
||||
|
||||
model statement {
|
||||
id Int @id @default(autoincrement())
|
||||
text String @db.VarChar(255)
|
||||
search_text String @default("") @db.VarChar(255)
|
||||
conversation String @default("") @db.VarChar(32)
|
||||
created_at DateTime? @default(now()) @db.DateTime(0)
|
||||
in_response_to String? @db.VarChar(255)
|
||||
search_in_response_to String @default("") @db.VarChar(255)
|
||||
persona String @default("") @db.VarChar(50)
|
||||
}
|
|
@ -1,28 +0,0 @@
|
|||
CREATE TABLE `statement` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`text` varchar(255) DEFAULT NOT NULL,
|
||||
`search_text` varchar(255) NOT NULL DEFAULT '',
|
||||
`conversation` varchar(32) NOT NULL DEFAULT '',
|
||||
`created_at` datetime DEFAULT current_timestamp(),
|
||||
`in_response_to` varchar(255) DEFAULT NULL,
|
||||
`search_in_response_to` varchar(255) NOT NULL DEFAULT '',
|
||||
`persona` varchar(50) NOT NULL DEFAULT '',
|
||||
PRIMARY KEY (`id`)
|
||||
);
|
||||
|
||||
CREATE TABLE `nsfw_content` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`text` varchar(255) NOT NULL DEFAULT '',
|
||||
`created_at` datetime DEFAULT current_timestamp(),
|
||||
`persona` varchar(50) NOT NULL DEFAULT '',
|
||||
PRIMARY KEY (`id`)
|
||||
);
|
||||
|
||||
CREATE TABLE `learn` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`command` varchar(255) NOT NULL,
|
||||
`result` varchar(255) NOT NULL,
|
||||
`user_id` varchar(255) NOT NULL,
|
||||
`created_at` datetime NOT NULL DEFAULT current_timestamp(),
|
||||
primary key (`id`)
|
||||
);
|
|
@ -1,25 +1,29 @@
|
|||
import { SapphireClient, container, LogLevel } from '@sapphire/framework'
|
||||
import { GatewayIntentBits, Partials, type Snowflake } from 'discord.js'
|
||||
import { ChatBot, NODE_ENV, MaaDatabase } from './modules'
|
||||
import { GatewayIntentBits, Partials } from 'discord.js'
|
||||
import { ChatBot, Config, NODE_ENV } from './modules'
|
||||
import { version } from '../package.json'
|
||||
import config from '../config.json'
|
||||
import { PrismaClient } from '../prisma'
|
||||
import semver from 'semver'
|
||||
|
||||
const config = new Config()
|
||||
|
||||
// Load pieces
|
||||
import './interaction-handlers/_load'
|
||||
import './listeners/_load'
|
||||
import './Commands/_load'
|
||||
|
||||
container.config = config
|
||||
container.prefix = config.bot.prefix
|
||||
container.version = version
|
||||
container.database = new MaaDatabase()
|
||||
container.dokdoAliases = ['dokdo', 'dok', 'Dokdo', 'Dok', '테스트']
|
||||
container.chatBot = new ChatBot(container.database)
|
||||
|
||||
const release = version
|
||||
.slice((semver.coerce(version)?.toString() + '-').length)
|
||||
.split('.')[1]
|
||||
|
||||
container.config = config
|
||||
container.prefix = config.bot.prefix
|
||||
container.version = version
|
||||
container.database = new PrismaClient()
|
||||
container.dokdoAliases = ['dokdo', 'dok', 'Dokdo', 'Dok', '테스트']
|
||||
container.chatBot = new ChatBot(container.database)
|
||||
container.lastUpdated = new Date('2024-09-28')
|
||||
|
||||
if (release.startsWith('e')) {
|
||||
container.release = 'EXPERIMENTAL'
|
||||
} else if (release.startsWith('d')) {
|
||||
|
@ -61,28 +65,14 @@ export default class MuffinBot extends SapphireClient {
|
|||
|
||||
declare module '@sapphire/framework' {
|
||||
interface Container {
|
||||
database: MaaDatabase
|
||||
database: PrismaClient
|
||||
chatBot: ChatBot
|
||||
prefix: string
|
||||
version: string
|
||||
dokdoAliases: string[]
|
||||
config: {
|
||||
bot: {
|
||||
owner_ID: Snowflake
|
||||
token: string
|
||||
}
|
||||
train: {
|
||||
user_ID: Snowflake
|
||||
}
|
||||
mysql: {
|
||||
user: string
|
||||
host: string
|
||||
password: string
|
||||
database: string
|
||||
port: number
|
||||
}
|
||||
}
|
||||
config: Config
|
||||
release: 'EXPERIMENTAL' | 'DEV' | 'PREVIEW' | 'RELEASE'
|
||||
lastUpdated: Date
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import './learning_data'
|
||||
import './deleteLearn'
|
||||
import './information'
|
||||
import './learn'
|
||||
import './help'
|
||||
import './list'
|
||||
|
|
|
@ -11,7 +11,6 @@ import {
|
|||
codeBlock,
|
||||
} from 'discord.js'
|
||||
import { ApplyOptions } from '@sapphire/decorators'
|
||||
import { type LearnData } from '../modules'
|
||||
|
||||
@ApplyOptions<Command.Options>({
|
||||
name: '삭제',
|
||||
|
@ -27,21 +26,22 @@ class DeleteLearnCommand extends Command {
|
|||
const CUSTOM_ID = 'maa$deleteLearn'
|
||||
const command = await args.rest('string').catch(() => null)
|
||||
const options: SelectMenuComponentOptionData[] = []
|
||||
const db = this.container.database
|
||||
const deleteDataList: string[] = []
|
||||
const [deleteDatas] = await db.database.execute<LearnData[]>(
|
||||
'SELECT * FROM learn WHERE command = ? AND user_id = ?;',
|
||||
[command, msg.author.id],
|
||||
)
|
||||
|
||||
if (!command) {
|
||||
return await msg.channel.send(
|
||||
return await msg.reply(
|
||||
`사용법: \n\`\`\`${(this.detailedDescription as DetailedDescriptionCommandObject).usage}\`\`\``,
|
||||
)
|
||||
}
|
||||
|
||||
const deleteDatas = await this.container.database.learn.findMany({
|
||||
where: {
|
||||
command,
|
||||
user_id: msg.author.id,
|
||||
},
|
||||
})
|
||||
|
||||
if (!deleteDatas) {
|
||||
return await msg.channel.send('해당하는 걸 찾ㅈ을 수 없어요.')
|
||||
return await msg.reply('해당하는 걸 찾ㅈ을 수 없어요.')
|
||||
}
|
||||
|
||||
for (let i = 1; i <= deleteDatas.length; i++) {
|
||||
|
|
65
src/Commands/information.ts
Normal file
65
src/Commands/information.ts
Normal file
|
@ -0,0 +1,65 @@
|
|||
import { ApplyOptions } from '@sapphire/decorators'
|
||||
import { Command, container } from '@sapphire/framework'
|
||||
import { Message } from 'discord.js'
|
||||
import { platform, arch } from 'os'
|
||||
|
||||
@ApplyOptions<Command.Options>({
|
||||
name: '정보',
|
||||
description: '머핀봇의 정보를 알ㄹ려줘요.',
|
||||
detailedDescription: {
|
||||
usage: '머핀아 정보',
|
||||
},
|
||||
})
|
||||
class InformationCommand extends Command {
|
||||
public async messageRun(msg: Message) {
|
||||
await msg.reply({
|
||||
embeds: [
|
||||
{
|
||||
title: `${this.container.client.user?.username}의 정ㅂ보`,
|
||||
fields: [
|
||||
{
|
||||
name: '구동ㅎ환경',
|
||||
value: `${platform()} ${arch()}`,
|
||||
inline: false,
|
||||
},
|
||||
{
|
||||
name: '버ㅈ전',
|
||||
value: this.container.version,
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: '채ㄴ널',
|
||||
value: this.container.release.toLowerCase(),
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: '최근 업ㄷ데이트 날짜',
|
||||
value: this.container.lastUpdated.toLocaleDateString('ko', {
|
||||
dateStyle: 'long',
|
||||
}),
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: '개ㅂ발자',
|
||||
value: (
|
||||
await this.container.client.users.fetch(
|
||||
this.container.config.bot.owner_ID,
|
||||
)
|
||||
).username,
|
||||
inline: false,
|
||||
},
|
||||
],
|
||||
thumbnail: {
|
||||
url: this.container.client.user!.displayAvatarURL()!,
|
||||
},
|
||||
},
|
||||
],
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
void container.stores.loadPiece({
|
||||
piece: InformationCommand,
|
||||
name: 'information',
|
||||
store: 'commands',
|
||||
})
|
|
@ -52,7 +52,6 @@ class LearnCommand extends Command {
|
|||
'간미',
|
||||
]
|
||||
const disallowed = ['@everyone', '@here', `<@${config.bot.owner_ID}>`]
|
||||
const db = this.container.database
|
||||
|
||||
for (const ig of ignore) {
|
||||
if (command.includes(ig)) {
|
||||
|
@ -66,10 +65,12 @@ class LearnCommand extends Command {
|
|||
}
|
||||
}
|
||||
|
||||
await db.learn.insert({
|
||||
await this.container.database.learn.create({
|
||||
data: {
|
||||
user_id: msg.author.id,
|
||||
command,
|
||||
result,
|
||||
},
|
||||
})
|
||||
await msg.reply(`${command}을/를 배웠ㅇ어요.`)
|
||||
}
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
import { ApplyOptions } from '@sapphire/decorators'
|
||||
import { type ResponseData } from '../modules'
|
||||
import { Command, container } from '@sapphire/framework'
|
||||
import { ApplyOptions } from '@sapphire/decorators'
|
||||
import { type Message } from 'discord.js'
|
||||
|
||||
@ApplyOptions<Command.Options>({
|
||||
|
@ -14,11 +13,15 @@ import { type Message } from 'discord.js'
|
|||
class LearnDataCommand extends Command {
|
||||
public async messageRun(msg: Message<true>) {
|
||||
const db = this.container.database
|
||||
const data = await db.statement.all()
|
||||
const nsfwData = await db.nsfwContent.all()
|
||||
const learnData = await db.learn.all()
|
||||
const userData = await db.learn.findOneAnotherKey('user_id', msg.author.id)
|
||||
const muffin: ResponseData[] = []
|
||||
const data = await db.statement.findMany()
|
||||
const nsfwData = await db.nsfw_content.findMany()
|
||||
const learnData = await db.learn.findMany()
|
||||
const userData = await db.learn.findMany({
|
||||
where: {
|
||||
user_id: msg.author.id,
|
||||
},
|
||||
})
|
||||
const muffin: any[] = []
|
||||
data.forEach(row => {
|
||||
if (row.persona === 'muffin') muffin.push(row)
|
||||
else return
|
||||
|
|
|
@ -13,13 +13,15 @@ import { Command, container } from '@sapphire/framework'
|
|||
class ListCommand extends Command {
|
||||
public async messageRun(msg: Message<boolean>) {
|
||||
const db = this.container.database
|
||||
const data = await db.learn.findOneAnotherKey('user_id', msg.author.id)
|
||||
const data = await db.learn.findMany({
|
||||
where: {
|
||||
user_id: msg.author.id,
|
||||
},
|
||||
})
|
||||
const list: string[] = []
|
||||
|
||||
if (!data[0]) {
|
||||
return await msg.channel.send(
|
||||
'당신ㄴ은 단어를 가르쳐준 기억이 없ㅅ는데요.',
|
||||
)
|
||||
return await msg.reply('당신ㄴ은 단어를 가르쳐준 기억이 없ㅅ는데요.')
|
||||
}
|
||||
|
||||
for (const listData of data) {
|
||||
|
|
|
@ -28,7 +28,7 @@ class DeleteLearnHandler extends InteractionHandler {
|
|||
public async run(interaction: StringSelectMenuInteraction) {
|
||||
await interaction.deferUpdate()
|
||||
|
||||
const id = interaction.values[0].slice(`${this._CUSTOM_ID}-`.length)
|
||||
const id = Number(interaction.values[0].slice(`${this._CUSTOM_ID}-`.length))
|
||||
const db = this.container.database
|
||||
const decimalRegexp = /^[0-9]/g
|
||||
|
||||
|
@ -36,7 +36,11 @@ class DeleteLearnHandler extends InteractionHandler {
|
|||
item.value.endsWith(id) ? item.label.match(decimalRegexp)![0] : null,
|
||||
)
|
||||
|
||||
await db.learn.delete(id)
|
||||
await db.learn.delete({
|
||||
where: {
|
||||
id,
|
||||
},
|
||||
})
|
||||
|
||||
await interaction.editReply({
|
||||
embeds: [
|
||||
|
|
|
@ -4,7 +4,7 @@ import { noPerm } from '../modules'
|
|||
import Dokdo from 'dokdo'
|
||||
|
||||
class MessageCreateListener extends Listener {
|
||||
public async run(msg: Message) {
|
||||
public async run(msg: Message<true>) {
|
||||
const prefix = this.container.prefix
|
||||
const dokdo = new Dokdo(this.container.client, {
|
||||
aliases: ['dokdo', 'dok'],
|
||||
|
@ -14,14 +14,13 @@ class MessageCreateListener extends Listener {
|
|||
})
|
||||
if (msg.author.bot) return
|
||||
if (msg.content.startsWith(prefix)) {
|
||||
if (this.container.release === 'PRE-RELEASE') {
|
||||
if (this.container.release !== 'RELEASE') {
|
||||
await msg.reply({
|
||||
embeds: [
|
||||
{
|
||||
title: '정식 출시 이전 버전 사용안내',
|
||||
description:
|
||||
`현재 이 버전의 ${this.container.client.user?.username}은 정식출시 되기 이전이라 많이 불안정할 수 있어요.\n` +
|
||||
`또한 이 버전의 ${this.container.client.user?.username}의 데이터는 정식버전과 연동이 안돼요.\n` +
|
||||
`만약 오류가 발견되면 ${(await this.container.client.users.fetch(this.container.config.bot.owner_ID)).username}님에게 알려주세요.\n`,
|
||||
color: 0xff0000,
|
||||
footer: {
|
||||
|
|
|
@ -1,19 +1,19 @@
|
|||
import type { Client, Message, TextChannel } from 'discord.js'
|
||||
import type { PrismaClient } from '../../prisma'
|
||||
import { container } from '@sapphire/framework'
|
||||
import type { MaaDatabase } from './database'
|
||||
|
||||
export default class ChatBot {
|
||||
public constructor(public db: MaaDatabase) {
|
||||
setInterval(async () => {
|
||||
this.db.ping()
|
||||
}, 60000)
|
||||
}
|
||||
public constructor(public db: PrismaClient) {}
|
||||
|
||||
public async getResponse(msg: Message): Promise<string> {
|
||||
const prefix = container.prefix
|
||||
const data = await this.db.statement.all()
|
||||
const data = await this.db.statement.findMany()
|
||||
const args = msg.content.slice(prefix.length).trim().split(/ +/g).join(' ')
|
||||
const learn = await this.db.learn.findOne(args)
|
||||
const learn = await this.db.learn.findMany({
|
||||
where: {
|
||||
command: args,
|
||||
},
|
||||
})
|
||||
const learnData = learn[Math.floor(Math.random() * learn.length)]
|
||||
const randomNumber = Math.round(Math.random() * (2 - 1) + 1)
|
||||
|
||||
|
@ -30,7 +30,7 @@ export default class ChatBot {
|
|||
|
||||
let response: string
|
||||
if ((msg.channel as TextChannel).nsfw) {
|
||||
const NSFWData = await this.db.nsfwContent.all()
|
||||
const NSFWData = await this.db.nsfw_content.findMany()
|
||||
const dataList = [...data, ...NSFWData]
|
||||
response = dataList[Math.floor(Math.random() * dataList.length)].text
|
||||
} else {
|
||||
|
@ -50,19 +50,23 @@ export default class ChatBot {
|
|||
if (msg.author.bot) return
|
||||
if (msg.author.id === container.config.train.user_ID) {
|
||||
const response = await this.getResponse(msg)
|
||||
await this.db.statement.insert({
|
||||
await this.db.statement.create({
|
||||
data: {
|
||||
text: msg.content,
|
||||
persona: 'muffin',
|
||||
in_response_to: response,
|
||||
},
|
||||
})
|
||||
} else {
|
||||
if (!(msg.channel as TextChannel).nsfw) return
|
||||
if (!msg.content.startsWith(prefix)) return
|
||||
const persona = `user:${msg.author.username.slice(0, 50).toLowerCase()}`
|
||||
const text = msg.content.replace(prefix, '')
|
||||
await this.db.nsfwContent.insert({
|
||||
await this.db.nsfw_content.create({
|
||||
data: {
|
||||
text,
|
||||
persona,
|
||||
},
|
||||
})
|
||||
}
|
||||
})
|
||||
|
|
13
src/modules/config.ts
Normal file
13
src/modules/config.ts
Normal file
|
@ -0,0 +1,13 @@
|
|||
import 'dotenv/config'
|
||||
|
||||
export default class MAAConfig {
|
||||
public readonly bot = {
|
||||
token: process.env.BOT_TOKEN!,
|
||||
owner_ID: process.env.BOT_OWNER_ID!,
|
||||
prefix: process.env.BOT_PREFIX!,
|
||||
}
|
||||
|
||||
public readonly train = {
|
||||
user_id: process.env.TRAIN_USER_ID!,
|
||||
}
|
||||
}
|
|
@ -1,27 +0,0 @@
|
|||
import { LearnTable, NSFWContentTable, StatementTable } from './model'
|
||||
import { container } from '@sapphire/framework'
|
||||
import { createPool } from 'mysql2/promise'
|
||||
|
||||
export class MaaDatabase {
|
||||
public readonly database = createPool({
|
||||
...container.config.mysql,
|
||||
keepAliveInitialDelay: 10000,
|
||||
enableKeepAlive: true,
|
||||
})
|
||||
.on('release', conn => {
|
||||
container.logger.debug(`[MaaDatabase] ${conn.threadId} Released.`)
|
||||
})
|
||||
.on('connection', conn => {
|
||||
container.logger.debug(`[MaaDatabase] ${conn.threadId} Connected.`)
|
||||
})
|
||||
public statement = new StatementTable(this.database)
|
||||
public nsfwContent = new NSFWContentTable(this.database)
|
||||
public learn = new LearnTable(this.database)
|
||||
|
||||
public ping() {
|
||||
this.database.getConnection().then(conn => {
|
||||
conn.ping()
|
||||
conn.release()
|
||||
})
|
||||
}
|
||||
}
|
|
@ -1,3 +0,0 @@
|
|||
export * from './database'
|
||||
export * from './type'
|
||||
export * from './model'
|
|
@ -1,3 +0,0 @@
|
|||
export * from './statement'
|
||||
export * from './learn'
|
||||
export * from './nsfwContent'
|
|
@ -1,72 +0,0 @@
|
|||
import type { BaseTable, LearnData } from '../type'
|
||||
import { type Pool } from 'mysql2/promise'
|
||||
import { Snowflake } from 'discord.js'
|
||||
import run from '../run'
|
||||
|
||||
export class LearnTable implements BaseTable<LearnData, string> {
|
||||
public readonly name = 'learn'
|
||||
public constructor(private _database: Pool) {}
|
||||
|
||||
public async all(): Promise<LearnData[]> {
|
||||
const [rows] = await this._database.execute<LearnData[]>(
|
||||
`SELECT * FROM ${this.name};`,
|
||||
)
|
||||
return rows
|
||||
}
|
||||
|
||||
public async findOne(key: string): Promise<LearnData[]> {
|
||||
const [rows] = await this._database.execute<LearnData[]>(
|
||||
`SELECT * FROM ${this.name} WHERE command = ?;`,
|
||||
[key],
|
||||
)
|
||||
return rows
|
||||
}
|
||||
|
||||
public async insert(data: {
|
||||
command: string
|
||||
result: string
|
||||
user_id: Snowflake
|
||||
}): Promise<void> {
|
||||
const db = await this._database.getConnection()
|
||||
|
||||
await run(db, async () => {
|
||||
await db.execute(
|
||||
`INSERT INTO ${this.name} (command, result, user_id) VALUES (?, ?, ?);`,
|
||||
[data.command, data.result, data.user_id],
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
public async update(data: {
|
||||
command: string
|
||||
result: string
|
||||
}): Promise<void> {
|
||||
const db = await this._database.getConnection()
|
||||
|
||||
await run(db, async () => {
|
||||
await db.execute(
|
||||
`UPDATE ${this.name} SET result = ? WHERE command = ?;`,
|
||||
[data.command, data.result],
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
public async delete(key: string): Promise<void> {
|
||||
const db = await this._database.getConnection()
|
||||
|
||||
await run(db, async () => {
|
||||
await db.execute(`DELETE FROM ${this.name} WHERE id = ?;`, [key])
|
||||
})
|
||||
}
|
||||
|
||||
public async findOneAnotherKey(
|
||||
key: 'id' | 'command' | 'result' | 'user_id' | 'created_at',
|
||||
data: any,
|
||||
): Promise<LearnData[]> {
|
||||
const [rows] = await this._database.execute<LearnData[]>(
|
||||
`SELECT * FROM ${this.name} WHERE ${key} = ?;`,
|
||||
[data],
|
||||
)
|
||||
return rows
|
||||
}
|
||||
}
|
|
@ -1,66 +0,0 @@
|
|||
import type { BaseTable, NSFWData } from '../type'
|
||||
import { type Pool } from 'mysql2/promise'
|
||||
import run from '../run'
|
||||
|
||||
export class NSFWContentTable implements BaseTable<NSFWData, number> {
|
||||
public readonly name = 'nsfw_content'
|
||||
public constructor(private _database: Pool) {}
|
||||
|
||||
public async all(): Promise<NSFWData[]> {
|
||||
const [rows] = await this._database.execute<NSFWData[]>(
|
||||
`SELECT * FROM ${this.name};`,
|
||||
)
|
||||
return rows
|
||||
}
|
||||
|
||||
public async findOne(key: number): Promise<NSFWData[]> {
|
||||
const [rows] = await this._database.execute<NSFWData[]>(
|
||||
`SELECT * FROM ${this.name} WHERE id = ?;`,
|
||||
[key],
|
||||
)
|
||||
return rows
|
||||
}
|
||||
|
||||
public async insert(data: { text: string; persona: string }): Promise<void> {
|
||||
const db = await this._database.getConnection()
|
||||
|
||||
await run(db, async () => {
|
||||
await db.execute(
|
||||
`INSERT INTO ${this.name} (text, persona) VALUES (?, ?);`,
|
||||
[data.text, data.persona],
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
public async update(data: { id: number; text: string }): Promise<void> {
|
||||
const db = await this._database.getConnection()
|
||||
|
||||
await run(db, async () => {
|
||||
await db.execute(`UPDATE ${this.name} SET text = ? WHERE id = ?;`, [
|
||||
data.text,
|
||||
data.id,
|
||||
])
|
||||
})
|
||||
}
|
||||
|
||||
public async delete(key: number): Promise<void> {
|
||||
const db = await this._database.getConnection()
|
||||
|
||||
await run(db, async () => {
|
||||
await db.execute(`DELETE FROM ${this} WHERE id = ?;`, [key])
|
||||
})
|
||||
}
|
||||
|
||||
public async findOneAnotherKey(
|
||||
key: 'id' | 'text' | 'persona' | 'created_at',
|
||||
data: any,
|
||||
): Promise<NSFWData[]> {
|
||||
const [rows] = await this._database.execute<NSFWData[]>(
|
||||
`SELECT *
|
||||
FROM ${this.name}
|
||||
WHERE ${key} = ?;`,
|
||||
[data],
|
||||
)
|
||||
return rows
|
||||
}
|
||||
}
|
|
@ -1,76 +0,0 @@
|
|||
import type { BaseTable, ResponseData } from '../type'
|
||||
import { type Pool } from 'mysql2/promise'
|
||||
import run from '../run'
|
||||
|
||||
export class StatementTable implements BaseTable<ResponseData, number> {
|
||||
public readonly name = 'statement'
|
||||
public constructor(private _database: Pool) {}
|
||||
|
||||
public async all(): Promise<ResponseData[]> {
|
||||
const [rows] = await this._database.execute<ResponseData[]>(
|
||||
`SELECT * FROM ${this.name};`,
|
||||
)
|
||||
return rows
|
||||
}
|
||||
|
||||
public async findOne(key: number): Promise<ResponseData[]> {
|
||||
const [rows] = await this._database.execute<ResponseData[]>(
|
||||
`SELECT * FROM ${this.name} WHERE id = ?;`,
|
||||
[key],
|
||||
)
|
||||
return rows
|
||||
}
|
||||
|
||||
public async insert(data: {
|
||||
text: string
|
||||
persona: string
|
||||
in_response_to: string
|
||||
}): Promise<void> {
|
||||
const db = await this._database.getConnection()
|
||||
|
||||
await run(db, async () => {
|
||||
await db.execute(
|
||||
`INSERT INTO ${this.name} (text, persona, in_response_to) VALUES (?, ?, ?);`,
|
||||
[data.text, data.persona, data.in_response_to],
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
public async update(data: { id: number; text: string }): Promise<void> {
|
||||
const db = await this._database.getConnection()
|
||||
|
||||
await run(db, async () => {
|
||||
await db.execute(`UPDATE ${this.name} SET text = ? WHERE id = ?;`, [
|
||||
data.text,
|
||||
data.id,
|
||||
])
|
||||
})
|
||||
}
|
||||
|
||||
public async delete(key: number): Promise<void> {
|
||||
const db = await this._database.getConnection()
|
||||
|
||||
await run(db, async () => {
|
||||
await db.execute(`DELETE FROM ${this.name} WHERE id = ?;`, [key])
|
||||
})
|
||||
}
|
||||
|
||||
public async findOneAnotherKey(
|
||||
key:
|
||||
| 'id'
|
||||
| 'text'
|
||||
| 'persona'
|
||||
| 'created_at'
|
||||
| 'search_text'
|
||||
| 'conversation'
|
||||
| 'in_response_to'
|
||||
| 'search_in_response_to',
|
||||
data: any,
|
||||
): Promise<ResponseData[]> {
|
||||
const [rows] = await this._database.execute<ResponseData[]>(
|
||||
`SELECT * FROM ${this.name} WHERE ${key} = ?;`,
|
||||
[data],
|
||||
)
|
||||
return rows
|
||||
}
|
||||
}
|
|
@ -1,14 +0,0 @@
|
|||
import { type PoolConnection } from 'mysql2/promise'
|
||||
|
||||
export default async function run(db: PoolConnection, fn: () => Promise<any>) {
|
||||
try {
|
||||
await db.beginTransaction()
|
||||
await fn()
|
||||
await db.commit()
|
||||
} catch (err) {
|
||||
console.error(err)
|
||||
await db.rollback()
|
||||
} finally {
|
||||
db.release()
|
||||
}
|
||||
}
|
|
@ -1,36 +0,0 @@
|
|||
import type { RowDataPacket } from 'mysql2/promise'
|
||||
import type { Snowflake } from 'discord.js'
|
||||
|
||||
export interface BaseData extends RowDataPacket {
|
||||
id: number
|
||||
text: string
|
||||
created_at: string
|
||||
persona: string
|
||||
}
|
||||
|
||||
export interface ResponseData extends BaseData {
|
||||
search_text: string
|
||||
conversation: string
|
||||
in_response_to: string | null
|
||||
search_in_response_to: string
|
||||
}
|
||||
|
||||
export interface LearnData extends RowDataPacket {
|
||||
id: number
|
||||
command: string
|
||||
result: string
|
||||
user_id: Snowflake
|
||||
created_at: string
|
||||
}
|
||||
|
||||
export { BaseData as NSFWData }
|
||||
|
||||
export interface BaseTable<T, V> {
|
||||
name: string
|
||||
all(): Promise<T[]>
|
||||
findOne(key: V): Promise<T[]>
|
||||
insert(data: any): Promise<void>
|
||||
update(data: any): Promise<void>
|
||||
delete(key: V): Promise<void>
|
||||
findOneAnotherKey(key: string, data: any): Promise<T[]>
|
||||
}
|
|
@ -1,14 +1,6 @@
|
|||
import { ResponseData, NSFWData, LearnData, MaaDatabase } from './database'
|
||||
import { NODE_ENV } from './env'
|
||||
import ChatBot from './ChatBot'
|
||||
import Config from './config'
|
||||
import noPerm from './noPerm'
|
||||
|
||||
export {
|
||||
ResponseData,
|
||||
MaaDatabase,
|
||||
LearnData,
|
||||
NODE_ENV,
|
||||
ChatBot,
|
||||
NSFWData,
|
||||
noPerm,
|
||||
}
|
||||
export { NODE_ENV, ChatBot, noPerm, Config }
|
||||
|
|
Loading…
Reference in a new issue