├── src
├── view
│ ├── styles
│ │ ├── abyss.css
│ │ ├── Genshin_Impact_Font.woff
│ │ ├── common.css
│ │ ├── character.css
│ │ └── profile.css
│ ├── images
│ │ ├── Lock.png
│ │ ├── Star
│ │ │ ├── 1.png
│ │ │ ├── 3.png
│ │ │ ├── 4.png
│ │ │ └── 5.png
│ │ ├── Element
│ │ │ ├── Cryo.png
│ │ │ ├── Geo.png
│ │ │ ├── Pyro.png
│ │ │ ├── Anemo.png
│ │ │ ├── Dendro.png
│ │ │ ├── Electro.png
│ │ │ └── Hydro.png
│ │ ├── City_background.png
│ │ ├── Header_background.png
│ │ └── ItemBackground
│ │ │ ├── Rarity_1.png
│ │ │ ├── Rarity_105.png
│ │ │ ├── Rarity_2.png
│ │ │ ├── Rarity_3.png
│ │ │ ├── Rarity_4.png
│ │ │ └── Rarity_5.png
│ ├── abyss.pug
│ ├── footer.pug
│ ├── index.html
│ ├── character.pug
│ └── profile.pug
├── assets
│ └── how-to-donate.png
├── modules
│ ├── checkCookie.js
│ ├── character.test.js
│ ├── renderCharacter.js
│ ├── profile.test.js
│ ├── renderProfile.js
│ └── database.js
├── utils
│ ├── handleError.js
│ └── dateFormat.js
├── plugins
│ ├── donate.js
│ ├── profile.js
│ ├── dailynote.js
│ ├── character.js
│ ├── abyss.js
│ └── wish.js
├── index.js
└── i18n.js
├── .vscode
└── settings.json
├── design
└── allCharacters_v1.png
├── .npmrc
├── .eslintrc.js
├── .github
└── workflows
│ └── build.prod.yml.disabled
├── package.json
├── .gitignore
├── README.md
├── LICENSE
└── yarn.lock
/src/view/styles/abyss.css:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/.vscode/settings.json:
--------------------------------------------------------------------------------
1 | {
2 | "compile-hero.disable-compile-files-on-did-save-code": true
3 | }
--------------------------------------------------------------------------------
/src/view/images/Lock.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/koishijs/koishi-plugin-genshin-legacy/HEAD/src/view/images/Lock.png
--------------------------------------------------------------------------------
/design/allCharacters_v1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/koishijs/koishi-plugin-genshin-legacy/HEAD/design/allCharacters_v1.png
--------------------------------------------------------------------------------
/src/view/images/Star/1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/koishijs/koishi-plugin-genshin-legacy/HEAD/src/view/images/Star/1.png
--------------------------------------------------------------------------------
/src/view/images/Star/3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/koishijs/koishi-plugin-genshin-legacy/HEAD/src/view/images/Star/3.png
--------------------------------------------------------------------------------
/src/view/images/Star/4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/koishijs/koishi-plugin-genshin-legacy/HEAD/src/view/images/Star/4.png
--------------------------------------------------------------------------------
/src/view/images/Star/5.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/koishijs/koishi-plugin-genshin-legacy/HEAD/src/view/images/Star/5.png
--------------------------------------------------------------------------------
/src/assets/how-to-donate.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/koishijs/koishi-plugin-genshin-legacy/HEAD/src/assets/how-to-donate.png
--------------------------------------------------------------------------------
/src/view/images/Element/Cryo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/koishijs/koishi-plugin-genshin-legacy/HEAD/src/view/images/Element/Cryo.png
--------------------------------------------------------------------------------
/src/view/images/Element/Geo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/koishijs/koishi-plugin-genshin-legacy/HEAD/src/view/images/Element/Geo.png
--------------------------------------------------------------------------------
/src/view/images/Element/Pyro.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/koishijs/koishi-plugin-genshin-legacy/HEAD/src/view/images/Element/Pyro.png
--------------------------------------------------------------------------------
/.npmrc:
--------------------------------------------------------------------------------
1 | canvas_binary_host_mirror=https://npm.taobao.org/mirrors/node-canvas-prebuilt/
2 | PUPPETEER_DOWNLOAD_HOST=https://npm.taobao.org/mirrors
--------------------------------------------------------------------------------
/src/view/images/City_background.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/koishijs/koishi-plugin-genshin-legacy/HEAD/src/view/images/City_background.png
--------------------------------------------------------------------------------
/src/view/images/Element/Anemo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/koishijs/koishi-plugin-genshin-legacy/HEAD/src/view/images/Element/Anemo.png
--------------------------------------------------------------------------------
/src/view/images/Element/Dendro.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/koishijs/koishi-plugin-genshin-legacy/HEAD/src/view/images/Element/Dendro.png
--------------------------------------------------------------------------------
/src/view/images/Element/Electro.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/koishijs/koishi-plugin-genshin-legacy/HEAD/src/view/images/Element/Electro.png
--------------------------------------------------------------------------------
/src/view/images/Element/Hydro.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/koishijs/koishi-plugin-genshin-legacy/HEAD/src/view/images/Element/Hydro.png
--------------------------------------------------------------------------------
/src/view/images/Header_background.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/koishijs/koishi-plugin-genshin-legacy/HEAD/src/view/images/Header_background.png
--------------------------------------------------------------------------------
/src/view/abyss.pug:
--------------------------------------------------------------------------------
1 | doctype html
2 | html
3 | head
4 | style
5 | include styles/common.css
6 | include styles/abyss.css
7 |
8 | body
--------------------------------------------------------------------------------
/src/view/styles/Genshin_Impact_Font.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/koishijs/koishi-plugin-genshin-legacy/HEAD/src/view/styles/Genshin_Impact_Font.woff
--------------------------------------------------------------------------------
/src/view/images/ItemBackground/Rarity_1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/koishijs/koishi-plugin-genshin-legacy/HEAD/src/view/images/ItemBackground/Rarity_1.png
--------------------------------------------------------------------------------
/src/view/images/ItemBackground/Rarity_105.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/koishijs/koishi-plugin-genshin-legacy/HEAD/src/view/images/ItemBackground/Rarity_105.png
--------------------------------------------------------------------------------
/src/view/images/ItemBackground/Rarity_2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/koishijs/koishi-plugin-genshin-legacy/HEAD/src/view/images/ItemBackground/Rarity_2.png
--------------------------------------------------------------------------------
/src/view/images/ItemBackground/Rarity_3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/koishijs/koishi-plugin-genshin-legacy/HEAD/src/view/images/ItemBackground/Rarity_3.png
--------------------------------------------------------------------------------
/src/view/images/ItemBackground/Rarity_4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/koishijs/koishi-plugin-genshin-legacy/HEAD/src/view/images/ItemBackground/Rarity_4.png
--------------------------------------------------------------------------------
/src/view/images/ItemBackground/Rarity_5.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/koishijs/koishi-plugin-genshin-legacy/HEAD/src/view/images/ItemBackground/Rarity_5.png
--------------------------------------------------------------------------------
/src/view/footer.pug:
--------------------------------------------------------------------------------
1 | footer
2 | p © koishijs/koishi-plugin-genshin 机智的小鱼君
3 | p All game data & media: © miHoYo
4 | p
5 | i For communication and learning only.
--------------------------------------------------------------------------------
/src/modules/checkCookie.js:
--------------------------------------------------------------------------------
1 | const { GenshinKit } = require('@genshin-kit/core')
2 | async function checkCookie(cookie, uid) {
3 | const App = new GenshinKit()
4 | try {
5 | await App.loginWithCookie(cookie).getUserInfo(uid)
6 | return true
7 | } catch (err) {
8 | return err
9 | }
10 | }
11 | module.exports = checkCookie
12 |
--------------------------------------------------------------------------------
/src/view/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | Document
9 |
10 |
11 |
12 | This file is the entry point for generate screenshots.
13 | Access this file first to use local media resources in CSS via file:// protocol.
14 |
15 |
16 |
--------------------------------------------------------------------------------
/.eslintrc.js:
--------------------------------------------------------------------------------
1 | /* eslint-disable no-undef */
2 | module.exports = {
3 | env: {
4 | browser: false,
5 | es2021: true,
6 | },
7 | extends: ['eslint:recommended'],
8 | // parser: '',
9 | parserOptions: {
10 | ecmaVersion: 12,
11 | sourceType: 'module',
12 | },
13 | plugins: [],
14 | rules: {
15 | indent: ['error', 2, { SwitchCase: 1 }],
16 | 'linebreak-style': ['warn', 'windows'],
17 | quotes: ['error', 'single'],
18 | semi: ['error', 'never'],
19 | },
20 | }
21 |
--------------------------------------------------------------------------------
/.github/workflows/build.prod.yml.disabled:
--------------------------------------------------------------------------------
1 | name: Production Build
2 |
3 | on:
4 | workflow_dispatch
5 |
6 | jobs:
7 | build:
8 | # 使用最新版ubantu虚拟机运行
9 | runs-on: ubuntu-latest
10 |
11 | steps:
12 | # from: https://github.com/actions/checkout
13 | - name: 本工作流
14 | uses: actions/checkout@master
15 |
16 | # 安装最新版 Node.js
17 | # from: https://github.com/actions/setup-node
18 | - name: 安装 Node.js
19 | uses: actions/setup-node@master
20 | with:
21 | node-version: 14
22 | registry-url: https://registry.npmjs.org/
23 |
24 | - name: 安装 yarn
25 | run: |
26 | npm install yarn -g
27 | - name: 安装项目依赖
28 | run: |
29 | yarn install
30 | - name: 测试项目
31 | run: |
32 | yarn test
33 | - name: 构建项目并打包发布
34 | run: |
35 | npm run publish:stable
36 | env:
37 | NODE_AUTH_TOKEN: ${{secrets.NPM_TOKEN}}
38 |
--------------------------------------------------------------------------------
/src/modules/character.test.js:
--------------------------------------------------------------------------------
1 | const path = require('path')
2 | const pug = require('pug')
3 | const { writeFileSync } = require('fs')
4 |
5 | const { uid, cookie } = require('./secret')
6 | const { GenshinKit, util } = require('@genshin-kit/core')
7 | const { template } = require('koishi-utils')
8 |
9 | template.set('genshin', require('../i18n'))
10 |
11 | function m(k) {
12 | return template(`genshin.profile.${k}`)
13 | }
14 |
15 | const genshin = new GenshinKit()
16 | genshin.loginWithCookie(cookie)
17 |
18 | genshin.getUserRoles(uid).then((data) => {
19 | const Filter = new util.CharactersFilter(data)
20 | const character = Filter.name('迪奥娜')
21 |
22 | console.log(character)
23 | const config = {
24 | pretty: 1,
25 | ...character,
26 | }
27 |
28 | const html = pug.renderFile(
29 | path.resolve(__dirname, '../view/character.pug'),
30 | config
31 | )
32 |
33 | writeFileSync(path.resolve(__dirname, '../view/character.dev.html'), html)
34 | })
35 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "koishi-plugin-genshin",
3 | "version": "2.0.0-beta.21",
4 | "description": "Genshin Impact player data fetcher and gacha simulator for Koishi.js",
5 | "main": "src/index.js",
6 | "repository": "https://github.com/Dragon-Fish/koishi-plugin-genshin",
7 | "author": "Dragon-Fish <824399619@qq.com>",
8 | "license": "Apache-2.0",
9 | "scripts": {
10 | "publish:stable": "npm publish --tag latest",
11 | "publish:next": "npm publish --tag next"
12 | },
13 | "dependencies": {
14 | "@genshin-kit/core": "^2.6.0",
15 | "genshin-gacha-kit": "^1.1.0",
16 | "pug": "^3.0.2"
17 | },
18 | "peerDependencies": {
19 | "koishi-core": "^3.13.1"
20 | },
21 | "devDependencies": {
22 | "@dragon-fish/bump": "^0.0.15",
23 | "koishi-core": "^3.13.1"
24 | },
25 | "keywords": [
26 | "genshin",
27 | "genshin-impact",
28 | "genshin-api",
29 | "hoyolab",
30 | "koishi",
31 | "mihoyo",
32 | "qqbot"
33 | ]
34 | }
--------------------------------------------------------------------------------
/src/utils/handleError.js:
--------------------------------------------------------------------------------
1 | const { template, segment } = require('koishi-utils')
2 | const { disableCookie } = require('../modules/database')
3 |
4 | const errorMap = {
5 | '-10001': '米游社协议异常,请更新 genshin-kit。',
6 | 10001: '登录状态异常,请检查 cookie。',
7 | 10101: '当前账号查询人数达到上限。',
8 | 10102: '被查询者米游社信息未公开。',
9 | }
10 |
11 | function getErrMsg(err) {
12 | return template(
13 | 'genshin.error',
14 | errorMap[err.code] || err.message || template('genshin.error_unknown'),
15 | err.code
16 | )
17 | }
18 |
19 | /**
20 | * @param {import('koishi-core').Session} session
21 | * @param {import('genshin-kit').GenshinKit} genshin
22 | * @param {*} err
23 | */
24 | async function handleError(session, genshin, err) {
25 | // 10001 - cookie 异常
26 | // 10101 - 次数耗尽
27 | if ([10001, 10101].includes(err.code)) {
28 | await session.send(template('genshin.donate.current_runout'))
29 | await disableCookie(session, genshin.cookie)
30 | return
31 | }
32 | return session.send(segment.quote(session.messageId) + getErrMsg(err))
33 | }
34 |
35 | module.exports = {
36 | errorMap,
37 | getErrMsg,
38 | handleError,
39 | }
40 |
--------------------------------------------------------------------------------
/src/utils/dateFormat.js:
--------------------------------------------------------------------------------
1 | const { Time } = require('koishi-core')
2 |
3 | /**
4 | * @param {string} fmt
5 | * @param {Date?} date
6 | * @returns
7 | */
8 | module.exports.dateFormat = function(fmt, date) {
9 | date = date || new Date()
10 | const o = {
11 | 'M+': date.getMonth() + 1, //月份
12 | 'd+': date.getDate(), //日
13 | 'h+': date.getHours(), //小时
14 | 'm+': date.getMinutes(), //分
15 | 's+': date.getSeconds(), //秒
16 | 'q+': Math.floor((date.getMonth() + 3) / 3), //季度
17 | S: date.getMilliseconds(), //毫秒
18 | }
19 | if (/(y+)/.test(fmt)) {
20 | fmt = fmt.replace(
21 | RegExp.$1,
22 | (date.getFullYear() + '').substr(4 - RegExp.$1.length)
23 | )
24 | }
25 | for (let k in o) {
26 | if (new RegExp('(' + k + ')').test(fmt)) {
27 | fmt = fmt.replace(
28 | RegExp.$1,
29 | RegExp.$1.length == 1 ? o[k] : ('00' + o[k]).substr(('' + o[k]).length)
30 | )
31 | }
32 | }
33 | return fmt
34 | }
35 |
36 | /**
37 | * @param {number} time
38 | * @returns
39 | */
40 | module.exports.getTimeLeft = function(time) {
41 | return Time.formatTime(time - Date.now())
42 | }
43 |
--------------------------------------------------------------------------------
/src/modules/renderCharacter.js:
--------------------------------------------------------------------------------
1 | const pug = require('pug')
2 | const { segment, template } = require('koishi-utils')
3 | const path = require('path')
4 |
5 | module.exports = async ({ uid, character, ctx }) => {
6 | let screenshot
7 |
8 | const options = {
9 | uid,
10 | ...character,
11 | }
12 | const html = pug.renderFile(
13 | path.resolve(__dirname, '../view/character.pug'),
14 | options
15 | )
16 |
17 | const page = await ctx.app.puppeteer.page();
18 |
19 | try {
20 | await page.goto(
21 | 'file:///' + path.resolve(__dirname, '../view/index.html')
22 | )
23 | await page.setContent(html)
24 | const { width, height } = await page.evaluate(() => {
25 | const ele = document.body;
26 | return {
27 | width: ele.scrollWidth,
28 | height: ele.scrollHeight,
29 | };
30 | });
31 | await page.setViewport({
32 | width: Math.ceil(width + 14),
33 | height: Math.ceil(height + 14),
34 | });
35 | screenshot = await page.screenshot({
36 | fullPage: true,
37 | type: 'jpeg',
38 | })
39 | } catch (err) {
40 | await page.close()
41 | return `错误:${err}`
42 | }
43 |
44 | await page.close()
45 | return (
46 | template('genshin.has_character', uid, character.name) +
47 | segment.image(screenshot)
48 | )
49 | }
50 |
--------------------------------------------------------------------------------
/src/modules/profile.test.js:
--------------------------------------------------------------------------------
1 | const pug = require('pug')
2 | const path = require('path')
3 | const { writeFileSync } = require('fs')
4 |
5 | const { uid, cookie } = require('./secret')
6 | const { GenshinKit, util } = require('@genshin-kit/core')
7 | const { template } = require('koishi-utils')
8 |
9 | template.set('genshin', require('../i18n'))
10 |
11 | function m(k) {
12 | return template(`genshin.profile.${k}`)
13 | }
14 |
15 | const genshin = new GenshinKit()
16 | genshin.loginWithCookie(cookie)
17 | Promise.all([genshin.getUserInfo(uid), genshin.getAllCharacters(uid)])
18 | .then(([userInfo, allCharacters]) => {
19 | let _stats = Object.assign({}, userInfo.stats)
20 | userInfo.stats = []
21 | for (key in _stats) {
22 | userInfo.stats.push({ desc: m('stats.' + key), count: _stats[key] })
23 | }
24 |
25 | allCharacters.forEach((item) => {
26 | item.activedConstellations = util.activedConstellations(item)
27 | })
28 |
29 | userInfo.avatars = allCharacters
30 |
31 | const options = {
32 | ui: {
33 | title: m('ui.title'),
34 | },
35 | uid,
36 | ...userInfo,
37 | }
38 | console.log(options)
39 | const html = pug.renderFile(
40 | path.resolve(__dirname, '../view/profile.pug'),
41 | options
42 | )
43 | writeFileSync(path.resolve(__dirname, '../view/profile.dev.html'), html)
44 | })
45 | .catch(console.error)
46 |
--------------------------------------------------------------------------------
/src/plugins/donate.js:
--------------------------------------------------------------------------------
1 | const path = require('path')
2 | const { readFileSync } = require('fs')
3 | const { segment, template } = require('koishi-utils')
4 | const { insertCookie } = require('../modules/database')
5 |
6 | const HOW_TO_DONATE = readFileSync(
7 | path.resolve(__dirname, '../assets/how-to-donate.png')
8 | )
9 |
10 | /**
11 | * @param {import('koishi-core').Context} ctx
12 | */
13 | function apply(ctx) {
14 | ctx
15 | .private()
16 | .command('genshin.donate [cookie:text]', '捐赠米游社账号')
17 | .alias('捐赠米游社账号', '捐赠原神账号')
18 | .usage('输入“米游社账号捐赠指南”查看教程')
19 | .check(({ session, options }, cookie) => {
20 | if (!cookie || options.help) return session.execute('genshin.donate.how')
21 | })
22 | .action(async ({ session }, cookie) => {
23 | return insertCookie(session, cookie)
24 | })
25 |
26 | ctx
27 | .command('genshin.donate.delete', '取消捐赠米游社账号')
28 | .alias('取消捐赠米游社账号', '取消捐赠原神账号')
29 | .option('user', '-u 指定捐赠者', { authority: 2 })
30 | .usage('输入“米游社账号捐赠指南”查看教程')
31 | .action(async ({ session, options }) => {
32 | return '该功能暂未实装,请联系 bot 管理员进行操作!'
33 | })
34 |
35 | ctx
36 | .command('genshin.donate.how', 'internal command', { hidden: true })
37 | .alias('米游社账号捐赠指南', '原神账号捐赠指南')
38 | .action(() => {
39 | return segment.image(HOW_TO_DONATE) + template('genshin.donate.help_extra')
40 | })
41 | }
42 |
43 | module.exports = {
44 | name: 'genshin/donate',
45 | apply,
46 | }
47 |
--------------------------------------------------------------------------------
/src/view/styles/common.css:
--------------------------------------------------------------------------------
1 | /* Common STyles */
2 | @font-face {
3 | font-family: 'Genshin';
4 | font-style: normal;
5 | font-weight: normal;
6 | src: url('Genshin_Impact_Font.woff')
7 | format('truetype');
8 | }
9 |
10 | * {
11 | box-sizing: border-box;
12 | }
13 |
14 | html,
15 | body {
16 | margin: 0;
17 | padding: 0;
18 | font-size: 14px;
19 | font-family: Genshin, '微软雅黑', 'Microsoft Yahei', Arial, Helvetica,
20 | sans-serif;
21 | background-color: white;
22 | }
23 |
24 | h1 {
25 | font-size: 1.4rem;
26 | font-weight: bold;
27 | text-align: center;
28 | padding: 1rem;
29 | border-radius: 8px;
30 | background-color: #eae3dd;
31 | box-shadow: 0 0 0 2px #d9d3c5 inset, 0 0 0 4px #eae3dd;
32 | }
33 |
34 | .box {
35 | margin: 1rem 0;
36 | }
37 |
38 | .box .boxTitle {
39 | margin: 2rem 0 1rem 0;
40 | padding: 0.5rem 1rem;
41 | text-align: center;
42 | color: #fff;
43 | font-size: 1.4rem;
44 | line-height: 2.4;
45 | background-image: url(../images/Header_background.png);
46 | background-position: center;
47 | background-repeat: no-repeat;
48 | background-size: auto 3rem;
49 | }
50 |
51 | .box .boxContent {
52 | border: 1px solid #ffdd95;
53 | background-color: #f5f5f5;
54 | padding: 0.4rem 0.75rem;
55 | border-radius: 8px;
56 | }
57 |
58 | footer {
59 | line-height: 1.2;
60 | text-align: right;
61 | color: gray;
62 | padding-right: 8px;
63 | border-right: 6px solid #ffdd95;
64 | border-radius: 4px;
65 | }
66 | footer p {
67 | margin: 0;
68 | }
69 |
70 | .flex {
71 | display: flex;
72 | }
73 | .flex-1 {
74 | flex: 1;
75 | }
76 |
--------------------------------------------------------------------------------
/src/modules/renderProfile.js:
--------------------------------------------------------------------------------
1 | const pug = require('pug')
2 | const { segment, template } = require('koishi-utils')
3 | const path = require('path')
4 | const { activedConstellations } = require('@genshin-kit/core').util
5 |
6 | function m(k) {
7 | return template(`genshin.profile.${k}`)
8 | }
9 |
10 | module.exports = async ({ uid, userInfo, allCharacters, ctx }) => {
11 | let screenshot
12 |
13 | let _stats = Object.assign({}, userInfo.stats)
14 | userInfo.stats = []
15 | for (key in _stats) {
16 | userInfo.stats.push({ desc: m('stats.' + key), count: _stats[key] })
17 | }
18 |
19 | allCharacters.forEach((item) => {
20 | item.activedConstellations = activedConstellations(item)
21 | })
22 |
23 | userInfo.avatars = allCharacters
24 |
25 | const options = {
26 | ui: {
27 | title: m('ui.title'),
28 | },
29 | uid,
30 | ...userInfo,
31 | }
32 | const html = pug.renderFile(
33 | path.resolve(__dirname, '../view/profile.pug'),
34 | options
35 | )
36 |
37 | const page = await ctx.app.puppeteer.page();
38 |
39 | try {
40 | await page.goto(
41 | 'file:///' + path.resolve(__dirname, '../view/index.html')
42 | )
43 | await page.setContent(html)
44 | const { width, height } = await page.evaluate(() => {
45 | const ele = document.body;
46 | return {
47 | width: ele.scrollWidth,
48 | height: ele.scrollHeight,
49 | };
50 | });
51 | await page.setViewport({
52 | width: Math.ceil(width + 14),
53 | height: Math.ceil(height + 14),
54 | });
55 | screenshot = await page.screenshot({
56 | fullPage: true,
57 | type: 'jpeg',
58 | })
59 | } catch (err) {
60 | await page.close()
61 | return `错误:${err}`
62 | }
63 |
64 | await page.close()
65 | return segment.image(screenshot)
66 | }
67 |
--------------------------------------------------------------------------------
/src/plugins/profile.js:
--------------------------------------------------------------------------------
1 | const { template, segment, Time } = require('koishi-utils')
2 | const { isValidCnUid } = require('@genshin-kit/core').util
3 | const { getErrMsg, handleError } = require('../utils/handleError')
4 | const { getGenshinApp } = require('../modules/database')
5 |
6 | /**
7 | * @param {import('koishi-core').Context} ctx
8 | */
9 | function apply(ctx) {
10 | ctx
11 | .command('genshin.profile', template('genshin.commands.profile'), {
12 | minInterval: Time.second * 30,
13 | })
14 | .userFields(['genshin_uid'])
15 | .option('uid', `-u ${template('genshin.commands.options_specify_uid')}`)
16 | .check(({ session, options }) => {
17 | let uid = options.uid || session.user.genshin_uid
18 | if (!uid) return template('genshin.not_registered')
19 | if (!isValidCnUid(uid)) return template('genshin.invalid_cn_uid')
20 | })
21 | .action(async ({ session, options }) => {
22 | let uid = options.uid || session.user.genshin_uid
23 | const genshin = await getGenshinApp(session, uid)
24 | if (!genshin) {
25 | return template('genshin.donate.daily_runout')
26 | }
27 |
28 | try {
29 | const [userInfo, allCharacters] = await Promise.all([
30 | genshin.getUserInfo(uid, true),
31 | genshin.getAllCharacters(uid, true),
32 | ])
33 |
34 | // 截图
35 | if (ctx.app.puppeteer) {
36 | let image = await require('../modules/renderProfile')({
37 | uid,
38 | userInfo,
39 | allCharacters,
40 | ctx,
41 | })
42 | return segment.quote(session.messageId) + image
43 | }
44 |
45 | // 文字版
46 | return '截图失败:未安装 koishi-plugin-puppeteer,请联系 bot 管理员。'
47 | } catch (err) {
48 | handleError(session, genshin, err)
49 | }
50 | })
51 | }
52 |
53 | module.exports = {
54 | name: 'genshin/profile',
55 | apply,
56 | }
57 |
--------------------------------------------------------------------------------
/src/view/character.pug:
--------------------------------------------------------------------------------
1 | mixin reliquaries(ctx)
2 | - const { name, icon, rarity , pos_name, level } = ctx;
3 | .item.flex(class=[`rarity-${rarity}`])
4 | img.icon(src=icon)
5 | .info
6 | .name= name
7 | .flex
8 | .rarity
9 | img(src=`images/Star/${rarity}.png`)
10 | .level +#{level}
11 |
12 | mixin constellations(ctx)
13 | - const { icon, is_actived } = ctx;
14 | div.item(class={ 'is-actived': is_actived, 'is-locked': !is_actived })
15 | img.icon(src=icon)
16 |
17 | doctype html
18 | html
19 | head
20 | style
21 | link(rel="stylesheet", href="styles/common.css")
22 | link(rel="stylesheet", href="styles/character.css")
23 |
24 | body
25 | .container(class=[`rarity-${rarity}`])
26 | .left
27 | .flex
28 | .portrait
29 | img(src=image)
30 | .title
31 | .name= name
32 | .level #{level}级
33 | .fetter 好感度 #{fetter}
34 |
35 | .right
36 | .card.constellations
37 | h2 命之座
38 | .content
39 | .flex
40 | each item in constellations
41 | +constellations(item)
42 | .desc 已激活: #{actived_constellation_num}
43 |
44 | .card.weapon
45 | h2 武器 - #{weapon.type_name}
46 | .content
47 | .flex
48 | .icon
49 | img(src=weapon.icon)
50 | .info
51 | .title
52 | .name= weapon.name
53 | .affix_level 精炼 #{weapon.affix_level} 阶
54 | .rarity
55 | img(src=`images/Star/${weapon.rarity}.png`)
56 | .level #{weapon.level}级
57 | hr
58 | .desc= weapon.desc
59 |
60 | .card.reliquaries
61 | h2 圣遗物
62 | .content
63 | each item in reliquaries
64 | +reliquaries(item)
65 |
66 | //- 脚注
67 | include footer.pug
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 | npm-debug.log*
5 | yarn-debug.log*
6 | yarn-error.log*
7 | lerna-debug.log*
8 |
9 | # Diagnostic reports (https://nodejs.org/api/report.html)
10 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
11 |
12 | # Runtime data
13 | pids
14 | *.pid
15 | *.seed
16 | *.pid.lock
17 |
18 | # Directory for instrumented libs generated by jscoverage/JSCover
19 | lib-cov
20 |
21 | # Coverage directory used by tools like istanbul
22 | coverage
23 | *.lcov
24 |
25 | # nyc test coverage
26 | .nyc_output
27 |
28 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
29 | .grunt
30 |
31 | # Bower dependency directory (https://bower.io/)
32 | bower_components
33 |
34 | # node-waf configuration
35 | .lock-wscript
36 |
37 | # Compiled binary addons (https://nodejs.org/api/addons.html)
38 | build/Release
39 |
40 | # Dependency directories
41 | node_modules/
42 | jspm_packages/
43 |
44 | # TypeScript v1 declaration files
45 | typings/
46 |
47 | # TypeScript cache
48 | *.tsbuildinfo
49 |
50 | # Optional npm cache directory
51 | .npm
52 |
53 | # Optional eslint cache
54 | .eslintcache
55 |
56 | # Microbundle cache
57 | .rpt2_cache/
58 | .rts2_cache_cjs/
59 | .rts2_cache_es/
60 | .rts2_cache_umd/
61 |
62 | # Optional REPL history
63 | .node_repl_history
64 |
65 | # Output of 'npm pack'
66 | *.tgz
67 |
68 | # Yarn Integrity file
69 | .yarn-integrity
70 |
71 | # dotenv environment variables file
72 | .env
73 | .env.test
74 |
75 | # parcel-bundler cache (https://parceljs.org/)
76 | .cache
77 |
78 | # Next.js build output
79 | .next
80 |
81 | # Nuxt.js build / generate output
82 | .nuxt
83 | dist
84 |
85 | # Gatsby files
86 | .cache/
87 | # Comment in the public line in if your project uses Gatsby and *not* Next.js
88 | # https://nextjs.org/blog/next-9-1#public-directory-support
89 | # public
90 |
91 | # vuepress build output
92 | .vuepress/dist
93 |
94 | # Serverless directories
95 | .serverless/
96 |
97 | # FuseBox cache
98 | .fusebox/
99 |
100 | # DynamoDB Local files
101 | .dynamodb/
102 |
103 | # TernJS port file
104 | .tern-port
105 |
106 | # This part is for develop
107 | dev/
108 | *.dev.*
109 |
110 | # Secrets
111 | secret*.*
112 | secret/
113 | !secret_sample/
114 | !secret*.sample.*
--------------------------------------------------------------------------------
/src/plugins/dailynote.js:
--------------------------------------------------------------------------------
1 | const { template, segment, Time } = require('koishi-utils')
2 | const { handleError } = require('../utils/handleError')
3 | const { getGenshinApp } = require('../modules/database')
4 |
5 | /**
6 | * @param {import('koishi-core').Context} ctx
7 | */
8 | function apply(ctx) {
9 | ctx
10 | .command('genshin.dailynote', template('genshin.commands.dailynote'), {
11 | minInterval: Time.second * 15,
12 | })
13 | .alias('genshin.note')
14 | .userFields(['genshin_uid'])
15 | .check(({ session }) => {
16 | let uid = session.user.genshin_uid
17 | if (!uid) return template('genshin.not_registered')
18 | })
19 | .action(async ({ session }) => {
20 | let uid = session.user.genshin_uid
21 | const genshin = await getGenshinApp(session, uid)
22 | if (!genshin?.selfUid?.includes('' + uid)) {
23 | return template('genshin.dailynote.no_permission', uid)
24 | }
25 |
26 | try {
27 | const {
28 | current_resin,
29 | max_resin,
30 | resin_recovery_time,
31 | finished_task_num,
32 | total_task_num,
33 | // is_extra_task_reward_received,
34 | remain_resin_discount_num,
35 | resin_discount_num_limit,
36 | current_expedition_num,
37 | max_expedition_num,
38 | expeditions,
39 | } = await genshin.getDailyNote(uid)
40 |
41 | return [
42 | `${segment.quote(session.messageId)}〓玩家 ${uid} 的实时便笺〓`,
43 | `原粹树脂:${current_resin}/${max_resin} (${
44 | resin_recovery_time > 0
45 | ? `${Time.formatTime(resin_recovery_time * 1000)} 后回满`
46 | : '已完全恢复'
47 | })`,
48 | `每日委托:已完成 ${finished_task_num}/${total_task_num} 个`,
49 | `周常副本:半价领取奖励机会 ${remain_resin_discount_num}/${resin_discount_num_limit} 次`,
50 | `〓探索派遣〓`,
51 | `已派出 ${current_expedition_num}/${max_expedition_num} 人`,
52 | expeditions
53 | .map(
54 | ({ avatar_side_icon, status, remained_time }) =>
55 | ` ${
56 | avatar_side_icon.split('_').pop().split('.')[0]
57 | } - ${template(
58 | `genshin.dailynote.status_${status.toLocaleLowerCase()}`
59 | )}${
60 | remained_time > 0
61 | ? ` (${Time.formatTime(remained_time * 1000)} 后结束)`
62 | : ''
63 | }`
64 | )
65 | .join('\n'),
66 | ].join('\n')
67 | } catch (e) {
68 | handleError(e)
69 | }
70 | })
71 | }
72 |
73 | module.exports = {
74 | name: 'genshin/dailynote',
75 | apply,
76 | }
77 |
--------------------------------------------------------------------------------
/src/view/profile.pug:
--------------------------------------------------------------------------------
1 | mixin statsCard(ctx)
2 | - const { desc, count } = ctx;
3 | .item
4 | .count= count
5 | .desc= desc
6 |
7 | mixin characterCard(ctx)
8 | - const { name, icon, level, rarity, fetter, element, activedConstellations } = ctx;
9 | div(class=['characterCard', 'rarity-' + rarity])
10 | .inner(style={'background-image':`url(images/ItemBackground/Rarity_${rarity}.png)`})
11 | .sideIcons
12 | .element
13 | img(src=`images/Element/${element}.png` alt=element)
14 | .constellation= activedConstellations
15 | img.avatar(src=icon)
16 | .characterName
17 | span.text #{name}
18 | .outer
19 | .characterLevel 等级 #{level}
20 | .characterFetter 好感 #{fetter}
21 |
22 | mixin cityCard(ctx)
23 | - const { level, exploration_percentage, icon, name } = ctx;
24 | .cityCard
25 | .left
26 | img.cityIcon(src=icon)
27 | .right
28 | .cityName= name
29 | .cityLevel 声望 #{level} 级
30 | .cityExploration 探索度 #{exploration_percentage / 10}%
31 |
32 | mixin homeCard(ctx)
33 | - const { name, icon, level, item_num, visit_num, comfort_num, comfort_level_name, comfort_level_icon } = ctx
34 | .homeCard(
35 | style={ 'background-image': 'url(' + icon + ')' }
36 | )
37 | .top
38 | .comfortInfo
39 | img(src=comfort_level_icon)
40 | .confortName= comfort_level_name
41 | .homeName= name
42 | .bottom
43 | .levelInfo
44 | .num= level
45 | .desc 信任等阶
46 | .comfortNum
47 | .num= comfort_num
48 | .desc 最高仙力
49 | .itemNum
50 | .num= item_num
51 | .desc 摆设数量
52 | .visitorNum
53 | .num= visit_num
54 | .desc 来访人数
55 |
56 |
57 | doctype html
58 | html
59 | head
60 | link(rel="stylesheet", href="styles/common.css")
61 | link(rel="stylesheet", href="styles/profile.css")
62 |
63 | body
64 | //- 标题
65 | .profile-container
66 | h1 玩家 #{uid} 的原神信息
67 |
68 | //- 数据总览
69 | .box
70 | .boxTitle 数据总览
71 | .boxContent
72 | .statsList
73 | each item in stats
74 | +statsCard(item)
75 |
76 | //- 角色列表
77 | .box
78 | .boxTitle 角色列表
79 | .boxContent
80 | .characterList
81 | each item in avatars
82 | +characterCard(item)
83 | p 右上角为命座数量
84 |
85 | //- 世界探索
86 | .box
87 | .boxTitle 世界探索
88 | .boxContent
89 | .cityList
90 | each item in world_explorations
91 | +cityCard(item)
92 |
93 | //- 尘歌壶
94 | .box
95 | .boxTitle 尘歌壶
96 | .boxContent
97 | .homeList
98 | each item in homes
99 | +homeCard(item)
100 |
101 | include footer.pug
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # koishi-plugin-genshin
2 |
3 | **Koishi 原神大礼包**(_Genshin Impact for Koishi.js_)是一个为[koishi](https://github.com/koishijs/koishi)设计的查询展示原神国服玩家数据以及抽卡模拟的插件。
4 |
5 | ## 特色功能
6 |
7 | 喜欢玩《原神》?懒得下载米游社?想和沙雕群友一起凹数据?那么本插件将会是您的不二之选!来给您的群聊安排一只能查询原神数据的 koishi 机械姬吧~
8 |
9 | 为您的机械姬安装本插件,玩家们无需打开米游社,向 koishi bot 发送指令,一键炫耀您的五星角色、五星武器和深渊数据!
10 |
11 | 想看看自己是不是非酋?想要成为下一个天选之人?向 koishi bot 发送指令,进行模拟抽卡吧!
12 |
13 | **截图展示**
14 |
15 |
16 | 玩家资料卡 (genshin.profile)
17 |
18 | 
19 |
20 |
21 |
22 |
23 | 角色展示卡 (genshin.character)
24 |
25 | 
26 |
27 |
28 |
29 | ## 安装方法
30 |
31 | ```bash
32 | # Via yarn
33 | yarn add koishi-plugin-genshin
34 | # Or via npm
35 | npm install koishi-plugin-genshin
36 | ```
37 |
38 | ## 使用指南
39 |
40 | 具体用法请使用`help genshin`查看(~~作者只是懒得写文档~~)
41 |
42 | ## 系统需求
43 |
44 | 需要配合最新版 koishi v3。需要配置数据库,暂时只保证兼容 MongoDB。
45 |
46 | 若要使用完整的“卡片”功能,需要配置并安装 [koishi-plugin-puppeteer](https://npmjs.com/package/koishi-plugin-puppeteer)。
47 |
48 | ## 配置项目
49 |
50 | 插件目前需要使用您的网页版米游社的 cookie 来获取玩家信息。
51 |
52 | > 使用网页版米游社登录 ,然后在控制台输入 `document.cookie`,返回的结果就是 cookie,一般来说只要没有进行修改密码、换绑手机或点击退出按钮等操作,当前 cookie 便能长久使用,如果失效了就重新登录获取一遍。
53 |
54 | > **⚠️ 注意 ⚠️**:请妥善保存您的 cookies。
绝对不要把你的 cookies 交给任何人!
绝对绝对不要把你的 cookies 交给任何人!!
绝对绝对绝对不要把你的 cookies 交给任何人!!!
55 |
56 | 安装插件,详见 [官方指南](https://koishi.js.org/guide/context.html)。
57 |
58 |
59 | 配置示例
60 |
61 | ```js
62 | // koishi.config.js
63 | module.exports = {
64 | plugins: {
65 | // ...
66 | genshin: {
67 | // 本插件的配置项
68 | }
69 | // ...
70 | }
71 | }
72 | // 当然如果您是 index.js 玩家也可以这样
73 | App.plugin(require('koishi-plugin-genshin'), {
74 | // 本插件的配置项
75 | })
76 | ```
77 |
78 |
79 |
80 | 自定义输出排版,可以使用 koishi 的 template 语法,由于字符串太多,[《请您读源码.jpg》](./i18n.js)。
81 |
82 | **可用配置项**
83 |
84 | - `cookie` {string} 您的米游社小饼干
85 | - `wish` {object}
86 | - `wish.enable` {boolean} 是否开启抽卡模拟器
87 | - `wish.customPools` {[AppGachaPool[]](https://github.com/genshin-kit/genshin-gacha-kit)} 自定义卡池(格式详见`genshin-gacha-kit`)
88 |
89 | ## 注意事项
90 |
91 | 一个米游社账号一天内只能查询 30 个玩家数据,目前还没有考虑负载均衡的设计,请自行处理频率控制!
92 |
93 | ~~【广告】如果你喜欢本插件,欢迎给作者打钱或者捐赠米游社账号。~~
94 |
95 | ---
96 |
97 | _For communication and learning only._
98 |
99 | **All game data & pictures from query, Genshin Impact font:** ©miHoYo
100 |
101 | > Copyright 2021 koishijs/机智的小鱼君
102 | >
103 | > Licensed under the Apache License, Version 2.0 (the "License");
104 | > you may not use this file except in compliance with the License.
105 | > You may obtain a copy of the License at
106 | >
107 | > http://www.apache.org/licenses/LICENSE-2.0
108 |
--------------------------------------------------------------------------------
/src/index.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @name koishi-plugin-genshin
3 | * @desc Genshin Impact plugin for Koishijs
4 | *
5 | * @author Koishijs(机智的小鱼君)
6 | * @license Apache-2.0
7 | */
8 | // Koishi
9 | const { segment, template, Time } = require('koishi-core')
10 |
11 | // GenshinKit
12 | const { isValidCnUid } = require('@genshin-kit/core').util
13 |
14 | /**
15 | * @command genshin
16 | * @param {import('koishi-core').Context} ctx
17 | */
18 | function apply(ctx, pOptions) {
19 | pOptions = {
20 | donate: {
21 | enable: true,
22 | },
23 | wish: {
24 | enable: false,
25 | officialPools: true,
26 | customPools: [],
27 | },
28 | ...pOptions,
29 | }
30 |
31 | // Set template
32 | template.set('genshin', { ...require('./i18n'), ...pOptions.i18n })
33 |
34 | // Register
35 | ctx
36 | .command('genshin [uid:posint]', template('genshin.commands.genshin'), {
37 | minInterval: Time.hour,
38 | })
39 | .alias('原神')
40 | .userFields(['genshin_uid'])
41 | .example('@我 genshin 100000001')
42 | .check(({ session, options }, uid) => {
43 | if (options.help) return
44 | const userFileds = session.user
45 | if (!uid) {
46 | const reply = userFileds.genshin_uid
47 | ? template('genshin.info_regestered', userFileds.genshin_uid)
48 | : template('genshin.not_registered')
49 | return segment('quote', { id: session.messageId }) + reply
50 | } else if (!isValidCnUid(uid)) {
51 | return (
52 | segment('quote', { id: session.messageId }) +
53 | template('genshin.invalid_cn_uid')
54 | )
55 | }
56 | })
57 | .action(async ({ session }, uid) => {
58 | const userFileds = session.user
59 | userFileds.genshin_uid = uid
60 | try {
61 | await session.user._update()
62 | } catch (err) {
63 | return (
64 | segment('quote', { id: session.messageId }) +
65 | template('genshin.faild', err.message)
66 | )
67 | }
68 | return (
69 | segment('quote', { id: session.messageId }) +
70 | template('genshin.successfully_registered')
71 | )
72 | })
73 |
74 | // Abyss
75 | ctx.plugin(require('./plugins/abyss'))
76 |
77 | // Daily Note
78 | ctx.plugin(require('./plugins/dailynote'))
79 |
80 | // Character Card
81 | ctx.plugin(require('./plugins/character'))
82 |
83 | // Profile
84 | ctx.plugin(require('./plugins/profile'))
85 |
86 | // Wish
87 | if (pOptions.wish.enable) {
88 | ctx.plugin(require('./plugins/wish'), pOptions)
89 | }
90 |
91 | // Donate
92 | ctx.plugin(require('./plugins/donate'))
93 |
94 | // Debug
95 | ctx.command('genshin.debug', 'DEBUG', { hidden: true }).action(() => {
96 | const hoyolabVer = genshin._hoyolabVersion()
97 | return [`hoyolab(cn): ${hoyolabVer}`].join('\n')
98 | })
99 | }
100 |
101 | module.exports = {
102 | name: 'genshin',
103 | apply,
104 | }
105 |
--------------------------------------------------------------------------------
/src/i18n.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | // command descriptions
3 | commands: {
4 | genshin: '《原神 Genshin Impact》功能',
5 | abyss: '查询原神深境螺旋数据。',
6 | character: '查询指定名称的角色的等级与装备信息。',
7 | dailynote: '查看本人实时便笺(需捐赠账号)。',
8 | donate:
9 | '捐赠您的米游社账号,提高每日查询上限。解锁无限次查询自己信息+实时便笺的特权!',
10 | profile: '查询玩家基本信息(宝箱、成就、声望)',
11 | options_specify_uid: '查询指定 uid 的信息',
12 | },
13 | // genshin
14 | info_regestered: '您的《原神》uid已注册为:{0}',
15 | invalid_cn_uid: '您输入的不是合法的《原神》国服uid~',
16 | not_registered:
17 | '您还没有注册您的《原神》用户信息,请艾特我输入“genshin 游戏内uid”进行注册~(注意打空格)',
18 | successfully_registered: '您的《原神》信息注册成功~',
19 | // abyss
20 | abyss: {
21 | cur_not_active: '玩家 {0} 还没有开启本期深境螺旋。',
22 | cur_is_active: '玩家 {0} 的本期深境螺旋数据:',
23 | prev_not_active: '玩家 {0} 没有参与上一期深境螺旋。',
24 | prev_is_active: '玩家 {0} 的上一期深境螺旋数据:',
25 | basic_data:
26 | '〓基本信息〓\n到达层数:{{ max_floor }}\n战斗次数:{{ total_win_times }}次通关/{{ total_battle_times }}总尝试\n获得渊星:{{ total_star }}',
27 | top_stats:
28 | '〓最佳战绩〓\n最强一击:{{ damage_rank }}\n最高承伤:{{ take_damage_rank }}\n最常出场:{{ reveal_rank }}\n元素爆发:{{ energy_skill_rank }}',
29 | cur_time: '本期深境螺旋将于【{0}】结束,还剩 {1}。',
30 | prev_time: '上期深境螺旋从 {0} 开始,于 {1} 结束。',
31 | },
32 | // characters
33 | has_character: '玩家 {0} 的 {1}:',
34 | no_character: '玩家 {0} 似乎没有名为 {1} 的角色。',
35 | character_basic:
36 | '{{ icon }}\n{{ name }} {{ rarity }}★ {{ constellation }}命\n等级:{{ level }}级,好感:{{ fetter }}级', // {{ icon }} -> 头像, {{ image }} -> 立绘
37 | character_weapon:
38 | '〓武器〓\n{{ name }} ({{ rarity }}★{{ type_name }})\n{{ level }}级 ({{ affix_level }}精炼)',
39 | character_reliquaries: '〓圣遗物〓\n{0}',
40 | has_x_star_characters: '玩家 {0} 一共拥有 {1} 个 {2}★ 角色。',
41 | no_x_star_character: '玩家 {0} 似乎没有 {1}★ 角色。',
42 | // 实时便笺
43 | dailynote: {
44 | no_permission:
45 | '未找到与 {0} 绑定的账号凭据,无法查看实时便笺。请捐赠账号后再试。',
46 | status_ongoing: '正在探索',
47 | status_finished: '探索完成',
48 | },
49 | // 用于玩家信息截图
50 | profile: {
51 | ui: {
52 | title: '玩家 {0} 的原神信息',
53 | stats_title: '数据总览',
54 | avatar_title: '角色列表',
55 | city_explorations_title: '城市探索',
56 | },
57 | stats: {
58 | active_day_number: '活跃天数',
59 | achievement_number: '达成成就',
60 | win_rate: 'win_rate',
61 | anemoculus_number: '风神瞳',
62 | geoculus_number: '岩神瞳',
63 | electroculus_number: '雷神瞳',
64 | avatar_number: '获得角色数',
65 | way_point_number: '解锁传送点',
66 | domain_number: '解锁秘境',
67 | spiral_abyss: '深境螺旋',
68 | precious_chest_number: '珍贵宝箱',
69 | luxurious_chest_number: '华丽宝箱',
70 | exquisite_chest_number: '精致宝箱',
71 | common_chest_number: '普通宝箱',
72 | magic_chest_number: '奇馈宝箱',
73 | },
74 | },
75 | // 贡献账号
76 | donate: {
77 | current_runout: '系统正在维护,请稍等片刻后再试一次!',
78 | daily_runout:
79 | '今日查询次数已耗尽,明天再来吧!\n想要提高查询上限吗?想要解锁无限次查询自己信息的特权吗?私信bot“捐赠米游社账号”了解详情。',
80 | upper_limit: '今日理论查询上限:{0} 名玩家(不包括捐赠者)',
81 | donor_thank: '感谢以下 {0} 位捐赠过账号的用户!\n{1}',
82 | help_extra: `〓您可能会用到的资料〓
83 | 米游社网页版: https://bbs.mihoyo.com/ys/
84 | 输入到控制台的代码: alert(document.cookie)
85 | *注意:请私信 bot 操作捐赠!!!`,
86 | },
87 | // error messages
88 | error: '出现了亿点问题:{0} ({1})',
89 | error_unknown: '未知问题',
90 | }
91 |
--------------------------------------------------------------------------------
/src/plugins/character.js:
--------------------------------------------------------------------------------
1 | const { template, segment, Time } = require('koishi-utils')
2 | const {
3 | isValidCnUid,
4 | CharactersFilter,
5 | activedConstellations,
6 | } = require('@genshin-kit/core').util
7 | const { handleError } = require('../utils/handleError')
8 | const { getGenshinApp } = require('../modules/database')
9 |
10 | /**
11 | * @param {import('koishi-core').Context} ctx
12 | */
13 | function apply(ctx) {
14 | ctx
15 | .command(
16 | 'genshin.character ',
17 | template('genshin.commands.character'),
18 | {
19 | minInterval: Time.second * 15,
20 | }
21 | )
22 | .option('uid', `-u ${template('genshin.commands.options_specify_uid')}`)
23 | .example('genshin.character 旅行者')
24 | .userFields(['genshin_uid'])
25 | .check(({ session, options }) => {
26 | let uid = options.uid || session.user.genshin_uid
27 | if (!uid) return template('genshin.not_registered')
28 | if (!isValidCnUid(uid)) return template('genshin.invalid_cn_uid')
29 | })
30 | .action(async ({ session, options }, name = '旅行者') => {
31 | let uid = options.uid || session.user.genshin_uid
32 | const genshin = await getGenshinApp(session, uid)
33 | if (!genshin) {
34 | return template('genshin.donate.daily_runout')
35 | }
36 |
37 | try {
38 | const allCharacters = await genshin.getAllCharacters(uid, true)
39 | const Filter = new CharactersFilter(allCharacters)
40 | const character = Filter.name(name)
41 |
42 | if (!character) return template('genshin.no_character', uid, name)
43 |
44 | // 截图
45 | if (ctx.app.puppeteer) {
46 | const image = await require('../modules/renderCharacter')({
47 | uid,
48 | character,
49 | ctx,
50 | })
51 | return segment.quote(session.messageId) + image
52 | }
53 |
54 | // 文字版
55 | return [
56 | template('genshin.has_character', uid, character.name),
57 | template('genshin.character_basic', {
58 | icon: segment('image', { url: character.icon }),
59 | image: segment('image', { url: character.image }),
60 | name: character.name,
61 | rarity: character.rarity,
62 | constellation: activedConstellations(character),
63 | level: character.level,
64 | fetter: character.fetter,
65 | }),
66 | template('genshin.character_weapon', {
67 | name: character.weapon.name,
68 | rarity: character.weapon.rarity,
69 | type_name: character.weapon.type_name,
70 | level: character.weapon.level,
71 | affix_level: character.weapon.affix_level,
72 | }),
73 | template(
74 | 'genshin.character_reliquaries',
75 | reliquariesFmt(character.reliquaries)
76 | ),
77 | ].join('\n')
78 | } catch (err) {
79 | handleError(session, genshin, err)
80 | }
81 | })
82 |
83 | function reliquariesFmt(reliquaries) {
84 | if (reliquaries.length < 1) return '无'
85 | let msg = ''
86 | reliquaries.forEach((item) => {
87 | msg += `${item.pos_name}:${item.name} (${item.rarity}★)\n`
88 | })
89 | return msg.trim()
90 | }
91 | }
92 |
93 | module.exports = {
94 | name: 'genshin/character',
95 | apply,
96 | }
97 |
--------------------------------------------------------------------------------
/src/view/styles/character.css:
--------------------------------------------------------------------------------
1 | /* palette */
2 | .rarity-5 {
3 | --bg-color: #fcf0d5;
4 | --card-color: #f4e4be;
5 | --border-color: #b2732b;
6 | --hr-color: #e0cda1;
7 | }
8 | .rarity-4 {
9 | --bg-color: #e4dffb;
10 | --card-color: #d3ccf3;
11 | --border-color: #63598b;
12 | --hr-color: #b9afe7;
13 | }
14 | .rarity-105 {
15 | --bg-color: #fad6d8;
16 | --card-color: #f1c1c4;
17 | --border-color: #b54f56;
18 | --hr-color: #eba8ac;
19 | }
20 |
21 | /* common */
22 | .flex {
23 | display: flex;
24 | }
25 | .container {
26 | display: flex;
27 | background-color: var(--bg-color);
28 | margin: 6px;
29 | box-shadow: 0 0 0 2px #fff inset, 0 0 0 2px var(--border-color);
30 | border-radius: 6px;
31 | }
32 |
33 | /* left */
34 | .container > .left {
35 | display: flex;
36 | position: relative;
37 | width: 40vw;
38 | }
39 | .container > .left .flex {
40 | align-items: center;
41 | }
42 | .container > .left .portrait {
43 | align-content: center;
44 | display: flex;
45 | }
46 | .container > .left .portrait img {
47 | width: 100%;
48 | height: auto;
49 | }
50 | .container > .left .title {
51 | position: absolute;
52 | width: 100%;
53 | bottom: 25%;
54 | left: 50%;
55 | text-align: center;
56 | transform: translateX(-50%);
57 | padding: 1rem;
58 | color: #fff;
59 | background-image: linear-gradient(
60 | 90deg,
61 | rgba(0, 0, 0, 0),
62 | rgba(0, 0, 0, 0.5),
63 | rgba(0, 0, 0, 0)
64 | );
65 | }
66 | .container > .left .title .name {
67 | font-size: 2rem;
68 | }
69 |
70 | /* right */
71 | .container > .right {
72 | flex: 1;
73 | padding: 1rem;
74 | position: relative;
75 | display: flex;
76 | flex-direction: column;
77 | gap: 1rem;
78 | justify-content: center;
79 | }
80 |
81 | /* card */
82 | .card h2 {
83 | font-weight: normal;
84 | background-color: var(--border-color);
85 | color: #fff;
86 | margin: 0;
87 | padding: 0.4rem;
88 | padding-left: 1rem;
89 | }
90 | .card .content {
91 | background-color: var(--card-color);
92 | padding: 1rem;
93 | }
94 | .card hr {
95 | border: none;
96 | border-bottom: 2px dashed var(--hr-color);
97 | margin: 0.4rem 0 0.4rem 0;
98 | padding: 0;
99 | }
100 |
101 | /* constellations */
102 | .constellations .flex {
103 | display: flex;
104 | gap: 1rem;
105 | justify-content: space-around;
106 | }
107 | .constellations .item .icon {
108 | height: auto;
109 | width: 100%;
110 | }
111 | .constellations .desc {
112 | margin-top: 0.5rem;
113 | }
114 | .constellations .item {
115 | flex: 1;
116 | position: relative;
117 | border-radius: 50%;
118 | }
119 | .constellations .item {
120 | border: 4px solid #fff;
121 | background-color: rgba(0, 0, 0, 0.1);
122 | }
123 | .constellations .item.is-locked::before {
124 | content: '';
125 | display: block;
126 | position: absolute;
127 | border-radius: 50%;
128 | width: 100%;
129 | height: 100%;
130 | background-color: rgba(0, 0, 0, 0.25);
131 | background-image: url(../images/Lock.png);
132 | background-repeat: no-repeat;
133 | background-position: 50%;
134 | background-size: 30px;
135 | }
136 |
137 | /* reliquaries */
138 | .reliquaries .content {
139 | display: flex;
140 | flex-wrap: wrap;
141 | gap: 1rem;
142 | }
143 | .reliquaries .item {
144 | width: calc(50% - 1rem);
145 | align-items: center;
146 | }
147 | .reliquaries .icon {
148 | width: 65px;
149 | }
150 | .reliquaries .info {
151 | display: flex;
152 | flex-direction: column;
153 | align-items: center;
154 | font-size: 1.2rem;
155 | }
156 | .reliquaries .info .name {
157 | font-size: 1.2rem;
158 | }
159 | .reliquaries .info .rarity img {
160 | height: 1em;
161 | }
162 |
163 | /* weapon */
164 | .weapon .content > .flex {
165 | gap: 1rem;
166 | align-items: center;
167 | }
168 | .weapon .icon img {
169 | width: 80px;
170 | }
171 | .weapon .info {
172 | flex: 1;
173 | }
174 | .weapon .rarity img {
175 | height: 1.4rem;
176 | }
177 | .weapon .info .title {
178 | gap: 8px;
179 | vertical-align: baseline;
180 | }
181 |
182 | .weapon .info .title > div {
183 | display: inline;
184 | }
185 |
186 | .weapon .info .title .name {
187 | font-size: 1.6rem;
188 | }
189 |
--------------------------------------------------------------------------------
/src/plugins/abyss.js:
--------------------------------------------------------------------------------
1 | const { template, segment, Time } = require('koishi-utils')
2 | const { isValidCnUid, CharactersFilter } = require('@genshin-kit/core').util
3 | const { dateFormat, getTimeLeft } = require('../utils/dateFormat')
4 | const { handleError } = require('../utils/handleError')
5 | const { getGenshinApp } = require('../modules/database')
6 |
7 | /**
8 | * @param {import('koishi-core').Context} ctx
9 | */
10 | function apply(ctx) {
11 | ctx
12 | .command('genshin.abyss', template('genshin.commands.abyss'), {
13 | minInterval: Time.second * 15,
14 | })
15 | // .shortcut(/(原神深渊|深境螺旋)/)
16 | .option(
17 | 'uid',
18 | `-u ${template('genshin.commands.options_specify_uid')}`
19 | )
20 | .option('previous', '-p 查询上一期的数据', { type: 'boolean' })
21 | .userFields(['genshin_uid'])
22 | .check(({ session, options }) => {
23 | let uid = options.uid || session.user.genshin_uid
24 | if (!uid) return template('genshin.not_registered')
25 | if (!isValidCnUid(uid)) return template('genshin.invalid_cn_uid')
26 | })
27 | .action(async ({ session, options }) => {
28 | let uid = options.uid || session.user.genshin_uid
29 | const genshin = await getGenshinApp(session, uid)
30 | if (!genshin) {
31 | return template('genshin.donate.daily_runout')
32 | }
33 |
34 | const type = options.previous ? 'prev' : 'cur'
35 |
36 | Promise.all([
37 | genshin.getAbyss(uid, type === 'cur' ? 1 : 2, true),
38 | genshin.getUserInfo(uid, true),
39 | ]).then(
40 | (data) => {
41 | // 变量
42 | const [abyssInfo, basicInfo] = data
43 | const Filter = new CharactersFilter(basicInfo.avatars || [])
44 | const {
45 | start_time,
46 | end_time,
47 | total_battle_times,
48 | total_win_times,
49 | max_floor,
50 | total_star,
51 | is_unlock,
52 | reveal_rank,
53 | damage_rank,
54 | take_damage_rank,
55 | energy_skill_rank,
56 | } = abyssInfo
57 |
58 | const startTimeStr = dateFormat(
59 | 'yyyy年M月d日 hh:mm:ss',
60 | new Date(start_time * 1000)
61 | )
62 | const endTimeStr = dateFormat(
63 | 'yyyy年M月d日 hh:mm:ss',
64 | new Date(end_time * 1000)
65 | )
66 |
67 | // 格式化的顶尖信息
68 | function formatedCharacterValue(data) {
69 | if (data.length < 1) return '无'
70 | let top = data[0]
71 | return `${Filter.id(top.avatar_id).name || top.avatar_id} ${
72 | top.value
73 | }`
74 | }
75 |
76 | // 格式化信息
77 | let msg = ''
78 | if (!is_unlock) {
79 | msg += template(`genshin.abyss.${type}_not_active`, uid)
80 | } else {
81 | msg += [
82 | template(`genshin.abyss.${type}_is_active`, uid),
83 | template('genshin.abyss.basic_data', {
84 | max_floor,
85 | total_win_times,
86 | total_battle_times,
87 | total_star,
88 | }),
89 | template('genshin.abyss.top_stats', {
90 | damage_rank: formatedCharacterValue(damage_rank),
91 | take_damage_rank: formatedCharacterValue(take_damage_rank),
92 | reveal_rank: formatedCharacterValue(reveal_rank),
93 | energy_skill_rank: formatedCharacterValue(energy_skill_rank),
94 | }),
95 | ].join('\n')
96 | }
97 |
98 | // 时间信息
99 | msg += '\n\n'
100 | if (type === 'cur') {
101 | msg += template(
102 | 'genshin.abyss.cur_time',
103 | endTimeStr,
104 | getTimeLeft(end_time * 1000)
105 | )
106 | } else {
107 | msg += template('genshin.abyss.prev_time', startTimeStr, endTimeStr)
108 | }
109 |
110 | // 发送
111 | session.send(segment('quote', { id: session.messageId }) + msg)
112 | },
113 | (err) => {
114 | handleError(session, genshin, err)
115 | }
116 | )
117 | })
118 | }
119 |
120 | module.exports = {
121 | name: 'genshin/abyss',
122 | apply,
123 | }
124 |
--------------------------------------------------------------------------------
/src/view/styles/profile.css:
--------------------------------------------------------------------------------
1 | /* 基础信息(神瞳数量等) */
2 | .profile-container {
3 | margin: 1rem;
4 | }
5 |
6 | .statsList {
7 | display: flex;
8 | flex-wrap: wrap;
9 | justify-content: space-between;
10 | }
11 |
12 | .statsList .item {
13 | box-sizing: border-box;
14 | width: 25%;
15 | padding: 8px;
16 | text-align: center;
17 | }
18 | .statsList .item .count {
19 | font-size: 1.6rem;
20 | }
21 | .statsList .item .desc {
22 | color: gray;
23 | }
24 |
25 | /* 简单角色卡 */
26 | .characterList {
27 | display: flex;
28 | flex-flow: wrap;
29 | justify-content: space-between;
30 | gap: 2rem;
31 | padding: 2rem;
32 | }
33 | .characterList .characterCard .inner {
34 | position: relative;
35 | background-size: cover;
36 | background-repeat: no-repeat;
37 | box-shadow: 0 0 8px rgba(0, 0, 0, 0.4);
38 | border-radius: 8px;
39 | color: white;
40 | }
41 | .characterList .characterCard .rarity {
42 | position: absolute;
43 | top: 130px;
44 | left: 50%;
45 | transform: translateX(-50%);
46 | z-index: 5;
47 | }
48 | .characterList .characterCard .rarity img {
49 | width: auto;
50 | height: 24px;
51 | }
52 | .characterList .characterCard img.avatar {
53 | height: 150px;
54 | width: auto;
55 | }
56 | .characterList .characterCard .characterName {
57 | font-size: 1.4rem;
58 | padding: 0.4rem;
59 | padding-top: 0;
60 | color: #000;
61 | text-align: center;
62 | position: relative;
63 | }
64 | .characterList .characterCard .characterName .text {
65 | position: relative;
66 | z-index: 1;
67 | }
68 | .characterList .characterCard .characterName img {
69 | position: absolute;
70 | left: 0;
71 | bottom: 0;
72 | width: 148px;
73 | height: auto;
74 | }
75 | .characterCard .element img {
76 | position: absolute;
77 | left: 0rem;
78 | top: 0rem;
79 | width: 2.4rem;
80 | height: 2.4rem;
81 | }
82 | .characterCard .constellation {
83 | position: absolute;
84 | right: -8px;
85 | top: -8px;
86 | border-radius: 50%;
87 | display: inline-block;
88 | width: 2rem;
89 | height: 2rem;
90 | text-align: center;
91 | font-size: 1.2rem;
92 | line-height: calc(2 / 1.2);
93 | color: #fff;
94 | }
95 | .characterCard.rarity-105 .constellation {
96 | background-color: #b54f56;
97 | box-shadow: 0 0 0 2px #fff inset, 0 0 0 2px #b54f56;
98 | }
99 | .characterCard.rarity-5 .constellation {
100 | background-color: #b2732b;
101 | box-shadow: 0 0 0 2px #fff inset, 0 0 0 2px #b2732b;
102 | }
103 | .characterCard.rarity-4 .constellation {
104 | background-color: #63598b;
105 | box-shadow: 0 0 0 2px #fff inset, 0 0 0 2px #63598b;
106 | }
107 | .characterList .characterCard .outer {
108 | margin-top: 0.4rem;
109 | font-size: 1.2rem;
110 | text-align: center;
111 | }
112 |
113 | /* 城市列表 */
114 | .cityList {
115 | display: flex;
116 | flex-flow: wrap;
117 | }
118 | .cityCard {
119 | background-image: url(../images/City_background.png);
120 | background-position: top left;
121 | background-repeat: no-repeat;
122 | background-size: 100% 120px;
123 | box-sizing: border-box;
124 | width: calc(50% - 2rem);
125 | height: 120px;
126 | color: #fff;
127 | border-radius: 8px;
128 | padding: 1rem;
129 | margin: 1rem;
130 | }
131 | .cityCard img {
132 | width: 90px;
133 | float: left;
134 | }
135 | .cityCard .right {
136 | height: 100%;
137 | display: flex;
138 | flex-direction: column;
139 | justify-content: center;
140 | }
141 | .cityCard .cityName {
142 | font-size: 30px;
143 | }
144 |
145 | /* 家园列表 */
146 | .homeList {
147 | display: flex;
148 | flex-flow: wrap;
149 | }
150 | .homeCard {
151 | background-position: top left;
152 | background-repeat: no-repeat;
153 | background-size: 100% 100%;
154 | box-sizing: border-box;
155 | width: calc(50% - 2rem);
156 | color: #fff;
157 | border-radius: 8px;
158 | margin: 1rem;
159 | }
160 | .homeCard .top {
161 | display: flex;
162 | padding: 1rem;
163 | }
164 | .homeCard .top .comfortInfo {
165 | flex: 1;
166 | display: flex;
167 | justify-items: center;
168 | align-items: center;
169 | font-size: 1.2rem;
170 | }
171 | .homeCard .top .comfortInfo img {
172 | width: 2rem;
173 | margin-right: 4px;
174 | }
175 | .homeCard .bottom {
176 | display: flex;
177 | margin: 1rem auto;
178 | background-color: rgba(0, 0, 0, 0.4);
179 | padding: 1rem 0.2rem;
180 | }
181 | .homeCard .bottom > div {
182 | flex: 1;
183 | text-align: center;
184 | }
185 | .homeCard .bottom > div .num {
186 | font-size: 1.5rem;
187 | }
188 |
--------------------------------------------------------------------------------
/src/modules/database.js:
--------------------------------------------------------------------------------
1 | const { Session } = require('koishi-core')
2 | const { GenshinKit } = require('@genshin-kit/core')
3 |
4 | const colName = 'hoyolab-cookies'
5 |
6 | /**
7 | * @param {Session} session
8 | * @param {string} cookie
9 | */
10 | async function insertCookie(session, cookie) {
11 | const { ltoken, ltuid } = getCookieObj(cookie)
12 | if (!ltoken || !ltuid) return '操作失败:提供的 cookie 不正确。'
13 |
14 | // check cookie, get roles
15 | let roles = []
16 | try {
17 | roles = await getBindingRoles(`ltoken=${ltoken}; ltuid=${ltuid}`)
18 | } catch (e) {
19 | return '操作失败:用户信息验证失败。'
20 | }
21 |
22 | if (roles.length < 1) {
23 | return '操作失败:该账号未绑定原神角色。'
24 | }
25 |
26 | // 操作数据库
27 | try {
28 | // 是否已经保存过
29 | const already = await session.database.mongo.db
30 | .collection(colName)
31 | .find({ ltuid })
32 | .limit(1)
33 | .toArray()
34 | if (already.length) {
35 | // 已保存过,刷新信息
36 | await session.database.mongo.db.collection(colName).updateOne(
37 | { ltuid },
38 | {
39 | $set: {
40 | owner: `${session.platform}:${session.userId}`,
41 | ltoken,
42 | game_uid: roles.map(({ game_uid }) => game_uid),
43 | },
44 | }
45 | )
46 | } else {
47 | // 未保存过,新增一行
48 | await session.database.mongo.db.collection(colName).insertOne({
49 | owner: `${session.platform}:${session.userId}`,
50 | ltuid,
51 | ltoken,
52 | game_uid: roles.map(({ game_uid }) => game_uid),
53 | last_disabled: '',
54 | })
55 | }
56 |
57 | // 成功!
58 | return `${
59 | already.length ? '成功刷新账号信息!' : '成功添加账号信息!'
60 | }已绑定原神游戏角色:\n${roles
61 | .map(
62 | ({ level, nickname, game_uid, region_name }) =>
63 | `Lv.${level} ${nickname} (${region_name}-${game_uid})`
64 | )
65 | .join('\n')}`
66 | } catch (e) {
67 | // 数据库错误
68 | session.logger('genshin').warn('保存 cookie 时发生数据库异常', e)
69 | return '保存失败:数据库异常,请联系 bot 管理员。'
70 | }
71 | }
72 |
73 | /**
74 | * @param {Session} session
75 | * @param {number} uid
76 | * @returns {GenshinKit}
77 | */
78 | async function getGenshinApp(session, uid) {
79 | const [self, common] = await Promise.all([
80 | session.database.mongo.db
81 | .collection(colName)
82 | .find({ game_uid: { $in: ['' + uid] } })
83 | .limit(1)
84 | .toArray(),
85 | session.database.mongo.db
86 | .collection(colName)
87 | .find({ last_disabled: { $ne: getFormatedToday() } })
88 | .limit(1)
89 | .toArray(),
90 | ])
91 |
92 | let data
93 | if (self.length) {
94 | // 本人账号
95 | data = self[0]
96 | } else if (common.length) {
97 | // 公共账号
98 | data = common[0]
99 | } else {
100 | // cookie 库耗尽
101 | return false
102 | }
103 | const { ltoken, ltuid, game_uid } = data
104 | const app = new GenshinKit().setCookie(`ltoken=${ltoken}; ltuid=${ltuid}`)
105 | app.selfUid = game_uid
106 | return app
107 | }
108 |
109 | /**
110 | * @param {Session} session
111 | * @param {string} cookie
112 | */
113 | async function disableCookie(session, cookie) {
114 | const { ltoken, ltuid } = getCookieObj(cookie)
115 | await session.database.mongo.db
116 | .collection('hoyolab-cookies')
117 | .updateOne(
118 | { ltuid, ltoken },
119 | { $set: { last_disabled: getFormatedToday() } }
120 | )
121 | return true
122 | }
123 |
124 | async function getBindingRoles(cookie) {
125 | const g = new GenshinKit()
126 | g.setCookie(cookie)
127 | const { data } = await g.request(
128 | 'get',
129 | 'https://api-takumi.mihoyo.com/binding/api/getUserGameRolesByCookie'
130 | )
131 | return data?.list.filter((item) =>
132 | ['hk4e_cn', 'hk4e_global'].includes(item.game_biz)
133 | )
134 | }
135 |
136 | /**
137 | *
138 | * @param {string} str
139 | * @returns {Record}
140 | */
141 | function getCookieObj(str) {
142 | const obj = {}
143 | str
144 | .split(';')
145 | .filter((i) => !!i)
146 | .forEach((item) => {
147 | const s = item.split('=')
148 | const key = s?.[0].trim()
149 | const val = s?.[1].trim() || ''
150 | if (!key) return
151 | obj[key] = val
152 | })
153 | return obj
154 | }
155 |
156 | function getFormatedToday() {
157 | const now = new Date()
158 | const timezoneCN = 8
159 | now.setHours(now.getHours() + timezoneCN)
160 | return now.toISOString().split('T')[0]
161 | }
162 |
163 | module.exports = {
164 | getGenshinApp,
165 | insertCookie,
166 | disableCookie,
167 | }
168 |
--------------------------------------------------------------------------------
/src/plugins/wish.js:
--------------------------------------------------------------------------------
1 | const { GenshinGachaKit, util } = require('genshin-gacha-kit')
2 | const { Logger } = require('koishi-core')
3 | const logger = new Logger('genshin')
4 | logger.log = logger.info
5 |
6 | const gachaTypeNameToId = {
7 | 角色: 301,
8 | 武器: 302,
9 | 常驻: 200,
10 | }
11 | const gachaAppTypeToTypeName = {
12 | character: '角色',
13 | weapon: '武器',
14 | permanent: '常驻',
15 | novice: '新手',
16 | }
17 |
18 | /**
19 | * @param {import('koishi-core').Context} ctx
20 | * @param {*} pOptions
21 | */
22 | function apply(ctx, pOptions) {
23 | ctx
24 | .command('genshin.wish')
25 | .alias('原神抽卡')
26 | .option('number', '-n ', { fallback: 1 })
27 | // .option('name','-n 选定抽卡时的卡池名称')
28 | .option('type', '-t 选定抽卡时的卡池类别(角色/武器/常驻)', {
29 | fallback: '角色',
30 | })
31 | .option('list-all', '-L 查看全部可用卡池')
32 | .option('list', '-l 查看相关类型卡池的内容')
33 | // .option('add', '-a 为本群添加卡池', { authority: 2 })
34 | // .option('remove', '-r 为本群移除卡池', { authority: 2 })
35 | // .channelFields(['genshin_gacha_pool'])
36 | .userFields(['genshin_gacha'])
37 | .check(check)
38 | .action(action)
39 |
40 | async function check({ session, options }) {
41 | logger.info('wish', options)
42 |
43 | if (options['list-all']) {
44 | const index = await util.getGachaIndex()
45 | const poolIds = index.map((i) => i.gacha_id)
46 |
47 | const queue = []
48 | poolIds.forEach((id) => queue.push(util.getGachaData(id)))
49 | let pools = await Promise.all(queue)
50 | pools = pools.map((i) => util.poolStructureConverter(i))
51 |
52 | return [
53 | `当前可用的卡池共有 ${pools.length} 个:`,
54 | pools
55 | .map((i) => {
56 | return `${i.name} (${i.upSSR.map((i) => i.name).join('、')} UP)`
57 | })
58 | .join('\n'),
59 | ].join('\n')
60 | }
61 |
62 | if (options.list) {
63 | if (!gachaTypeNameToId[options.list])
64 | return '没有这个类型的卡池:' + options.list
65 | let pool = await util.getOfficialGachaPool(
66 | gachaTypeNameToId[options.list]
67 | )
68 | pool = util.poolStructureConverter(pool)
69 | return [
70 | `${pool.name}`,
71 | `${gachaAppTypeToTypeName[pool.type]}池`,
72 | `5星 UP:${pool.upSSR.map((i) => i.name).join('、') || '无'}`,
73 | `4星 UP:${pool.upSR.map((i) => i.name).join('、') || '无'}`,
74 | ].join('\n')
75 | }
76 | }
77 |
78 | async function action({ session, options }) {
79 | const gacha = new GenshinGachaKit()
80 | let genshin_gacha = session.user.genshin_gacha
81 | console.log('1111', genshin_gacha)
82 | const { counter, result } = genshin_gacha
83 | console.log('2222', { counter, result })
84 |
85 | if (counter?.total !== undefined && result?.r !== undefined) {
86 | gacha.setCounter(counter)
87 | gacha.setResult(result)
88 | }
89 |
90 | let number = options.number
91 | number = Math.min(90, number)
92 | number = Math.max(1, number)
93 |
94 | let pool = await util.getOfficialGachaPool(gachaTypeNameToId[options.type])
95 | if (!pool) return `无法拉取 ${options.type} 的卡池信息。`
96 | pool = util.poolStructureConverter(pool)
97 |
98 | gacha.setGachaPool(pool)
99 |
100 | const items = gacha.multiWish(number)
101 |
102 | const savedData = {
103 | counter: gacha.getCounter(),
104 | result: gacha.getResult(),
105 | }
106 | console.log('保存数据', savedData)
107 | genshin_gacha = savedData
108 | await session.user._update()
109 | console.log('数据库中的数据', session.user.genshin_gacha)
110 |
111 | return `抽到了 ${items
112 | .map((i) => `${i.name}(${i.rarity}星)x${i.count}`)
113 | .join('、')}`
114 | }
115 |
116 | ctx
117 | .command('genshin.backpack')
118 | .option('reset', '-R')
119 | .userFields(['genshin_gacha'])
120 | .action(async ({ session, options }) => {
121 | let genshin_gacha = session.user.genshin_gacha
122 | if (!genshin_gacha) return '您还未抽过卡。'
123 |
124 | if (options.reset) {
125 | const gacha = new GenshinGachaKit()
126 | gacha.clearCounter().clearResult()
127 | genshin_gacha = {
128 | counter: gacha.getCounter(),
129 | result: gacha.getResult(),
130 | }
131 | await session.user._update()
132 | return '已重置背包。'
133 | }
134 |
135 | const { counter, result } = Object.assign({}, genshin_gacha)
136 | console.log(JSON.stringify({ counter, result }))
137 | return [
138 | `您共抽了 ${counter.total} 次卡`,
139 | `五星角色:${result.ssr
140 | .filter((i) => i.type === 'character')
141 | .map((i) => i.name)
142 | .join('、') || '无'}`,
143 | `五星武器:${result.ssr
144 | .filter((i) => i.type === 'weapon')
145 | .map((i) => i.name)
146 | .join('、') || '无'}`,
147 | `距离上一次五星 ${counter.lastSSR} 抽,您现在${
148 | counter.ensureSSR === 1 ? '有' : '没有'
149 | }大保底。`,
150 | ].join('\n')
151 | })
152 |
153 | ctx
154 | .command('arr')
155 | .userFields(['arr_test'])
156 | .action(async ({ session }) => {
157 | const arr = session.user.arr_test || []
158 | arr.push({ length: { foo: { bar: [arr.length] } } })
159 | session.user.arr_test = arr
160 | await session.user._update()
161 | return JSON.stringify(arr)
162 | })
163 | }
164 |
165 | module.exports = {
166 | name: 'genshin/wish',
167 | apply,
168 | }
169 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Apache License
2 | Version 2.0, January 2004
3 | http://www.apache.org/licenses/
4 |
5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6 |
7 | 1. Definitions.
8 |
9 | "License" shall mean the terms and conditions for use, reproduction,
10 | and distribution as defined by Sections 1 through 9 of this document.
11 |
12 | "Licensor" shall mean the copyright owner or entity authorized by
13 | the copyright owner that is granting the License.
14 |
15 | "Legal Entity" shall mean the union of the acting entity and all
16 | other entities that control, are controlled by, or are under common
17 | control with that entity. For the purposes of this definition,
18 | "control" means (i) the power, direct or indirect, to cause the
19 | direction or management of such entity, whether by contract or
20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 | outstanding shares, or (iii) beneficial ownership of such entity.
22 |
23 | "You" (or "Your") shall mean an individual or Legal Entity
24 | exercising permissions granted by this License.
25 |
26 | "Source" form shall mean the preferred form for making modifications,
27 | including but not limited to software source code, documentation
28 | source, and configuration files.
29 |
30 | "Object" form shall mean any form resulting from mechanical
31 | transformation or translation of a Source form, including but
32 | not limited to compiled object code, generated documentation,
33 | and conversions to other media types.
34 |
35 | "Work" shall mean the work of authorship, whether in Source or
36 | Object form, made available under the License, as indicated by a
37 | copyright notice that is included in or attached to the work
38 | (an example is provided in the Appendix below).
39 |
40 | "Derivative Works" shall mean any work, whether in Source or Object
41 | form, that is based on (or derived from) the Work and for which the
42 | editorial revisions, annotations, elaborations, or other modifications
43 | represent, as a whole, an original work of authorship. For the purposes
44 | of this License, Derivative Works shall not include works that remain
45 | separable from, or merely link (or bind by name) to the interfaces of,
46 | the Work and Derivative Works thereof.
47 |
48 | "Contribution" shall mean any work of authorship, including
49 | the original version of the Work and any modifications or additions
50 | to that Work or Derivative Works thereof, that is intentionally
51 | submitted to Licensor for inclusion in the Work by the copyright owner
52 | or by an individual or Legal Entity authorized to submit on behalf of
53 | the copyright owner. For the purposes of this definition, "submitted"
54 | means any form of electronic, verbal, or written communication sent
55 | to the Licensor or its representatives, including but not limited to
56 | communication on electronic mailing lists, source code control systems,
57 | and issue tracking systems that are managed by, or on behalf of, the
58 | Licensor for the purpose of discussing and improving the Work, but
59 | excluding communication that is conspicuously marked or otherwise
60 | designated in writing by the copyright owner as "Not a Contribution."
61 |
62 | "Contributor" shall mean Licensor and any individual or Legal Entity
63 | on behalf of whom a Contribution has been received by Licensor and
64 | subsequently incorporated within the Work.
65 |
66 | 2. Grant of Copyright License. Subject to the terms and conditions of
67 | this License, each Contributor hereby grants to You a perpetual,
68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 | copyright license to reproduce, prepare Derivative Works of,
70 | publicly display, publicly perform, sublicense, and distribute the
71 | Work and such Derivative Works in Source or Object form.
72 |
73 | 3. Grant of Patent License. Subject to the terms and conditions of
74 | this License, each Contributor hereby grants to You a perpetual,
75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 | (except as stated in this section) patent license to make, have made,
77 | use, offer to sell, sell, import, and otherwise transfer the Work,
78 | where such license applies only to those patent claims licensable
79 | by such Contributor that are necessarily infringed by their
80 | Contribution(s) alone or by combination of their Contribution(s)
81 | with the Work to which such Contribution(s) was submitted. If You
82 | institute patent litigation against any entity (including a
83 | cross-claim or counterclaim in a lawsuit) alleging that the Work
84 | or a Contribution incorporated within the Work constitutes direct
85 | or contributory patent infringement, then any patent licenses
86 | granted to You under this License for that Work shall terminate
87 | as of the date such litigation is filed.
88 |
89 | 4. Redistribution. You may reproduce and distribute copies of the
90 | Work or Derivative Works thereof in any medium, with or without
91 | modifications, and in Source or Object form, provided that You
92 | meet the following conditions:
93 |
94 | (a) You must give any other recipients of the Work or
95 | Derivative Works a copy of this License; and
96 |
97 | (b) You must cause any modified files to carry prominent notices
98 | stating that You changed the files; and
99 |
100 | (c) You must retain, in the Source form of any Derivative Works
101 | that You distribute, all copyright, patent, trademark, and
102 | attribution notices from the Source form of the Work,
103 | excluding those notices that do not pertain to any part of
104 | the Derivative Works; and
105 |
106 | (d) If the Work includes a "NOTICE" text file as part of its
107 | distribution, then any Derivative Works that You distribute must
108 | include a readable copy of the attribution notices contained
109 | within such NOTICE file, excluding those notices that do not
110 | pertain to any part of the Derivative Works, in at least one
111 | of the following places: within a NOTICE text file distributed
112 | as part of the Derivative Works; within the Source form or
113 | documentation, if provided along with the Derivative Works; or,
114 | within a display generated by the Derivative Works, if and
115 | wherever such third-party notices normally appear. The contents
116 | of the NOTICE file are for informational purposes only and
117 | do not modify the License. You may add Your own attribution
118 | notices within Derivative Works that You distribute, alongside
119 | or as an addendum to the NOTICE text from the Work, provided
120 | that such additional attribution notices cannot be construed
121 | as modifying the License.
122 |
123 | You may add Your own copyright statement to Your modifications and
124 | may provide additional or different license terms and conditions
125 | for use, reproduction, or distribution of Your modifications, or
126 | for any such Derivative Works as a whole, provided Your use,
127 | reproduction, and distribution of the Work otherwise complies with
128 | the conditions stated in this License.
129 |
130 | 5. Submission of Contributions. Unless You explicitly state otherwise,
131 | any Contribution intentionally submitted for inclusion in the Work
132 | by You to the Licensor shall be under the terms and conditions of
133 | this License, without any additional terms or conditions.
134 | Notwithstanding the above, nothing herein shall supersede or modify
135 | the terms of any separate license agreement you may have executed
136 | with Licensor regarding such Contributions.
137 |
138 | 6. Trademarks. This License does not grant permission to use the trade
139 | names, trademarks, service marks, or product names of the Licensor,
140 | except as required for reasonable and customary use in describing the
141 | origin of the Work and reproducing the content of the NOTICE file.
142 |
143 | 7. Disclaimer of Warranty. Unless required by applicable law or
144 | agreed to in writing, Licensor provides the Work (and each
145 | Contributor provides its Contributions) on an "AS IS" BASIS,
146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 | implied, including, without limitation, any warranties or conditions
148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 | PARTICULAR PURPOSE. You are solely responsible for determining the
150 | appropriateness of using or redistributing the Work and assume any
151 | risks associated with Your exercise of permissions under this License.
152 |
153 | 8. Limitation of Liability. In no event and under no legal theory,
154 | whether in tort (including negligence), contract, or otherwise,
155 | unless required by applicable law (such as deliberate and grossly
156 | negligent acts) or agreed to in writing, shall any Contributor be
157 | liable to You for damages, including any direct, indirect, special,
158 | incidental, or consequential damages of any character arising as a
159 | result of this License or out of the use or inability to use the
160 | Work (including but not limited to damages for loss of goodwill,
161 | work stoppage, computer failure or malfunction, or any and all
162 | other commercial damages or losses), even if such Contributor
163 | has been advised of the possibility of such damages.
164 |
165 | 9. Accepting Warranty or Additional Liability. While redistributing
166 | the Work or Derivative Works thereof, You may choose to offer,
167 | and charge a fee for, acceptance of support, warranty, indemnity,
168 | or other liability obligations and/or rights consistent with this
169 | License. However, in accepting such obligations, You may act only
170 | on Your own behalf and on Your sole responsibility, not on behalf
171 | of any other Contributor, and only if You agree to indemnify,
172 | defend, and hold each Contributor harmless for any liability
173 | incurred by, or claims asserted against, such Contributor by reason
174 | of your accepting any such warranty or additional liability.
175 |
176 | END OF TERMS AND CONDITIONS
177 |
178 | APPENDIX: How to apply the Apache License to your work.
179 |
180 | To apply the Apache License to your work, attach the following
181 | boilerplate notice, with the fields enclosed by brackets "[]"
182 | replaced with your own identifying information. (Don't include
183 | the brackets!) The text should be enclosed in the appropriate
184 | comment syntax for the file format. We also recommend that a
185 | file or class name and description of purpose be included on the
186 | same "printed page" as the copyright notice for easier
187 | identification within third-party archives.
188 |
189 | Copyright [yyyy] [name of copyright owner]
190 |
191 | Licensed under the Apache License, Version 2.0 (the "License");
192 | you may not use this file except in compliance with the License.
193 | You may obtain a copy of the License at
194 |
195 | http://www.apache.org/licenses/LICENSE-2.0
196 |
197 | Unless required by applicable law or agreed to in writing, software
198 | distributed under the License is distributed on an "AS IS" BASIS,
199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200 | See the License for the specific language governing permissions and
201 | limitations under the License.
202 |
--------------------------------------------------------------------------------
/yarn.lock:
--------------------------------------------------------------------------------
1 | # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
2 | # yarn lockfile v1
3 |
4 |
5 | "@babel/helper-validator-identifier@^7.15.7":
6 | version "7.15.7"
7 | resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.15.7.tgz#220df993bfe904a4a6b02ab4f3385a5ebf6e2389"
8 | integrity sha512-K4JvCtQqad9OY2+yTU8w+E82ywk/fe+ELNlt1G8z3bVGlZfn/hOcQQsUhGhW/N+tb3fxK800wLtKOE/aM0m72w==
9 |
10 | "@babel/parser@^7.6.0", "@babel/parser@^7.9.6":
11 | version "7.16.4"
12 | resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.16.4.tgz#d5f92f57cf2c74ffe9b37981c0e72fee7311372e"
13 | integrity sha512-6V0qdPUaiVHH3RtZeLIsc+6pDhbYzHR8ogA8w+f+Wc77DuXto19g2QUwveINoS34Uw+W8/hQDGJCx+i4n7xcng==
14 |
15 | "@babel/types@^7.6.1", "@babel/types@^7.9.6":
16 | version "7.16.0"
17 | resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.16.0.tgz#db3b313804f96aadd0b776c4823e127ad67289ba"
18 | integrity sha512-PJgg/k3SdLsGb3hhisFvtLOw5ts113klrpLuIPtCJIU+BB24fqq6lf8RWqKJEjzqXR9AEH1rIb5XTqwBHB+kQg==
19 | dependencies:
20 | "@babel/helper-validator-identifier" "^7.15.7"
21 | to-fast-properties "^2.0.0"
22 |
23 | "@dragon-fish/bump@^0.0.15":
24 | version "0.0.15"
25 | resolved "https://registry.yarnpkg.com/@dragon-fish/bump/-/bump-0.0.15.tgz#b04e9e3e3be11b8166228fc14da427c18386dfb8"
26 | integrity sha512-ObYvwi0vNhKZ1eerSpOK6ThfIF4bruzLxuc74joC4ag9uc3VocKHzVqdzIlWKh43dTwmdEisawOOJ/iobI/70A==
27 | dependencies:
28 | axios "^0.21.1"
29 | commander "^7.1.0"
30 | fs-extra "^9.1.0"
31 |
32 | "@genshin-kit/core@^2.6.0":
33 | version "2.6.0"
34 | resolved "https://registry.yarnpkg.com/@genshin-kit/core/-/core-2.6.0.tgz#f76827d6739b3ae77b79845ea26898fba59b9526"
35 | integrity sha512-382F4DV6gAdJ8c/830Tg2Nhlw4lYX5mcoW7V/d6gP8F1NdmN2vnQ6kXDkK/rvp1q3GgED8rz0jTGqrrVxM2Gxg==
36 | dependencies:
37 | axios "^0.24.0"
38 | tslib "^2.3.1"
39 |
40 | "@koa/router@^10.1.1":
41 | version "10.1.1"
42 | resolved "https://registry.yarnpkg.com/@koa/router/-/router-10.1.1.tgz#8e5a85c9b243e0bc776802c0de564561e57a5f78"
43 | integrity sha512-ORNjq5z4EmQPriKbR0ER3k4Gh7YGNhWDL7JBW+8wXDrHLbWYKYSJaOJ9aN06npF5tbTxe2JBOsurpJDAvjiXKw==
44 | dependencies:
45 | debug "^4.1.1"
46 | http-errors "^1.7.3"
47 | koa-compose "^4.1.0"
48 | methods "^1.1.2"
49 | path-to-regexp "^6.1.0"
50 |
51 | "@types/accepts@*":
52 | version "1.3.5"
53 | resolved "https://registry.yarnpkg.com/@types/accepts/-/accepts-1.3.5.tgz#c34bec115cfc746e04fe5a059df4ce7e7b391575"
54 | integrity sha512-jOdnI/3qTpHABjM5cx1Hc0sKsPoYCp+DP/GJRGtDlPd7fiV9oXGGIcjW/ZOxLIvjGz8MA+uMZI9metHlgqbgwQ==
55 | dependencies:
56 | "@types/node" "*"
57 |
58 | "@types/body-parser@*":
59 | version "1.19.2"
60 | resolved "https://registry.yarnpkg.com/@types/body-parser/-/body-parser-1.19.2.tgz#aea2059e28b7658639081347ac4fab3de166e6f0"
61 | integrity sha512-ALYone6pm6QmwZoAgeyNksccT9Q4AWZQ6PvfwR37GT6r6FWUPguq6sUmNGSMV2Wr761oQoBxwGGa6DR5o1DC9g==
62 | dependencies:
63 | "@types/connect" "*"
64 | "@types/node" "*"
65 |
66 | "@types/connect@*":
67 | version "3.4.35"
68 | resolved "https://registry.yarnpkg.com/@types/connect/-/connect-3.4.35.tgz#5fcf6ae445e4021d1fc2219a4873cc73a3bb2ad1"
69 | integrity sha512-cdeYyv4KWoEgpBISTxWvqYsVy444DOqehiF3fM3ne10AmJ62RSyNkUnxMJXHQWRQQX2eR94m5y1IZyDwBjV9FQ==
70 | dependencies:
71 | "@types/node" "*"
72 |
73 | "@types/content-disposition@*":
74 | version "0.5.4"
75 | resolved "https://registry.yarnpkg.com/@types/content-disposition/-/content-disposition-0.5.4.tgz#de48cf01c79c9f1560bcfd8ae43217ab028657f8"
76 | integrity sha512-0mPF08jn9zYI0n0Q/Pnz7C4kThdSt+6LD4amsrYDDpgBfrVWa3TcCOxKX1zkGgYniGagRv8heN2cbh+CAn+uuQ==
77 |
78 | "@types/cookies@*":
79 | version "0.7.7"
80 | resolved "https://registry.yarnpkg.com/@types/cookies/-/cookies-0.7.7.tgz#7a92453d1d16389c05a5301eef566f34946cfd81"
81 | integrity sha512-h7BcvPUogWbKCzBR2lY4oqaZbO3jXZksexYJVFvkrFeLgbZjQkU4x8pRq6eg2MHXQhY0McQdqmmsxRWlVAHooA==
82 | dependencies:
83 | "@types/connect" "*"
84 | "@types/express" "*"
85 | "@types/keygrip" "*"
86 | "@types/node" "*"
87 |
88 | "@types/express-serve-static-core@^4.17.18":
89 | version "4.17.26"
90 | resolved "https://registry.yarnpkg.com/@types/express-serve-static-core/-/express-serve-static-core-4.17.26.tgz#5d9a8eeecb9d5f9d7fc1d85f541512a84638ae88"
91 | integrity sha512-zeu3tpouA043RHxW0gzRxwCHchMgftE8GArRsvYT0ByDMbn19olQHx5jLue0LxWY6iYtXb7rXmuVtSkhy9YZvQ==
92 | dependencies:
93 | "@types/node" "*"
94 | "@types/qs" "*"
95 | "@types/range-parser" "*"
96 |
97 | "@types/express@*":
98 | version "4.17.13"
99 | resolved "https://registry.yarnpkg.com/@types/express/-/express-4.17.13.tgz#a76e2995728999bab51a33fabce1d705a3709034"
100 | integrity sha512-6bSZTPaTIACxn48l50SR+axgrqm6qXFIxrdAKaG6PaJk3+zuUr35hBlgT7vOmJcum+OEaIBLtHV/qloEAFITeA==
101 | dependencies:
102 | "@types/body-parser" "*"
103 | "@types/express-serve-static-core" "^4.17.18"
104 | "@types/qs" "*"
105 | "@types/serve-static" "*"
106 |
107 | "@types/http-assert@*":
108 | version "1.5.3"
109 | resolved "https://registry.yarnpkg.com/@types/http-assert/-/http-assert-1.5.3.tgz#ef8e3d1a8d46c387f04ab0f2e8ab8cb0c5078661"
110 | integrity sha512-FyAOrDuQmBi8/or3ns4rwPno7/9tJTijVW6aQQjK02+kOQ8zmoNg2XJtAuQhvQcy1ASJq38wirX5//9J1EqoUA==
111 |
112 | "@types/http-errors@*":
113 | version "1.8.1"
114 | resolved "https://registry.yarnpkg.com/@types/http-errors/-/http-errors-1.8.1.tgz#e81ad28a60bee0328c6d2384e029aec626f1ae67"
115 | integrity sha512-e+2rjEwK6KDaNOm5Aa9wNGgyS9oSZU/4pfSMMPYNOfjvFI0WVXm29+ITRFr6aKDvvKo7uU1jV68MW4ScsfDi7Q==
116 |
117 | "@types/keygrip@*":
118 | version "1.0.2"
119 | resolved "https://registry.yarnpkg.com/@types/keygrip/-/keygrip-1.0.2.tgz#513abfd256d7ad0bf1ee1873606317b33b1b2a72"
120 | integrity sha512-GJhpTepz2udxGexqos8wgaBx4I/zWIDPh/KOGEwAqtuGDkOUJu5eFvwmdBX4AmB8Odsr+9pHCQqiAqDL/yKMKw==
121 |
122 | "@types/koa-compose@*":
123 | version "3.2.5"
124 | resolved "https://registry.yarnpkg.com/@types/koa-compose/-/koa-compose-3.2.5.tgz#85eb2e80ac50be95f37ccf8c407c09bbe3468e9d"
125 | integrity sha512-B8nG/OoE1ORZqCkBVsup/AKcvjdgoHnfi4pZMn5UwAPCbhk/96xyv284eBYW8JlQbQ7zDmnpFr68I/40mFoIBQ==
126 | dependencies:
127 | "@types/koa" "*"
128 |
129 | "@types/koa@*":
130 | version "2.13.4"
131 | resolved "https://registry.yarnpkg.com/@types/koa/-/koa-2.13.4.tgz#10620b3f24a8027ef5cbae88b393d1b31205726b"
132 | integrity sha512-dfHYMfU+z/vKtQB7NUrthdAEiSvnLebvBjwHtfFmpZmB7em2N3WVQdHgnFq+xvyVgxW5jKDmjWfLD3lw4g4uTw==
133 | dependencies:
134 | "@types/accepts" "*"
135 | "@types/content-disposition" "*"
136 | "@types/cookies" "*"
137 | "@types/http-assert" "*"
138 | "@types/http-errors" "*"
139 | "@types/keygrip" "*"
140 | "@types/koa-compose" "*"
141 | "@types/node" "*"
142 |
143 | "@types/koa__router@^8.0.8":
144 | version "8.0.11"
145 | resolved "https://registry.yarnpkg.com/@types/koa__router/-/koa__router-8.0.11.tgz#d7b37e6db934fc072ea1baa2ab92bc8ac4564f3e"
146 | integrity sha512-WXgKWpBsbS14kzmzD9LeFapOIa678h7zvUHxDwXwSx4ETKXhXLVUAToX6jZ/U7EihM7qwyD9W/BZvB0MRu7MTQ==
147 | dependencies:
148 | "@types/koa" "*"
149 |
150 | "@types/lru-cache@^5.1.1":
151 | version "5.1.1"
152 | resolved "https://registry.yarnpkg.com/@types/lru-cache/-/lru-cache-5.1.1.tgz#c48c2e27b65d2a153b19bfc1a317e30872e01eef"
153 | integrity sha512-ssE3Vlrys7sdIzs5LOxCzTVMsU7i9oa/IaW92wF32JFb3CVczqOkru2xspuKczHEbG3nvmPY7IFqVmGGHdNbYw==
154 |
155 | "@types/mime@^1":
156 | version "1.3.2"
157 | resolved "https://registry.yarnpkg.com/@types/mime/-/mime-1.3.2.tgz#93e25bf9ee75fe0fd80b594bc4feb0e862111b5a"
158 | integrity sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw==
159 |
160 | "@types/node@*":
161 | version "16.11.12"
162 | resolved "https://registry.yarnpkg.com/@types/node/-/node-16.11.12.tgz#ac7fb693ac587ee182c3780c26eb65546a1a3c10"
163 | integrity sha512-+2Iggwg7PxoO5Kyhvsq9VarmPbIelXP070HMImEpbtGCoyWNINQj4wzjbQCXzdHTRXnqufutJb5KAURZANNBAw==
164 |
165 | "@types/qs@*":
166 | version "6.9.7"
167 | resolved "https://registry.yarnpkg.com/@types/qs/-/qs-6.9.7.tgz#63bb7d067db107cc1e457c303bc25d511febf6cb"
168 | integrity sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw==
169 |
170 | "@types/range-parser@*":
171 | version "1.2.4"
172 | resolved "https://registry.yarnpkg.com/@types/range-parser/-/range-parser-1.2.4.tgz#cd667bcfdd025213aafb7ca5915a932590acdcdc"
173 | integrity sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw==
174 |
175 | "@types/serve-static@*":
176 | version "1.13.10"
177 | resolved "https://registry.yarnpkg.com/@types/serve-static/-/serve-static-1.13.10.tgz#f5e0ce8797d2d7cc5ebeda48a52c96c4fa47a8d9"
178 | integrity sha512-nCkHGI4w7ZgAdNkrEu0bv+4xNV/XDqW+DydknebMOQwkpDGx8G+HTlj7R7ABI8i8nKxVw0wtKPi1D+lPOkh4YQ==
179 | dependencies:
180 | "@types/mime" "^1"
181 | "@types/node" "*"
182 |
183 | "@types/ws@^7.4.7":
184 | version "7.4.7"
185 | resolved "https://registry.yarnpkg.com/@types/ws/-/ws-7.4.7.tgz#f7c390a36f7a0679aa69de2d501319f4f8d9b702"
186 | integrity sha512-JQbbmxZTZehdc2iszGKs5oC3NFnjeay7mtAWrdt7qNtAVK0g19muApzAy4bm9byz79xa2ZnO/BOBC2R8RC5Lww==
187 | dependencies:
188 | "@types/node" "*"
189 |
190 | accepts@^1.3.5:
191 | version "1.3.7"
192 | resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.7.tgz#531bc726517a3b2b41f850021c6cc15eaab507cd"
193 | integrity sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==
194 | dependencies:
195 | mime-types "~2.1.24"
196 | negotiator "0.6.2"
197 |
198 | acorn@^7.1.1:
199 | version "7.4.1"
200 | resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.4.1.tgz#feaed255973d2e77555b83dbc08851a6c63520fa"
201 | integrity sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==
202 |
203 | asap@~2.0.3:
204 | version "2.0.6"
205 | resolved "https://registry.yarnpkg.com/asap/-/asap-2.0.6.tgz#e50347611d7e690943208bbdafebcbc2fb866d46"
206 | integrity sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY=
207 |
208 | assert-never@^1.2.1:
209 | version "1.2.1"
210 | resolved "https://registry.yarnpkg.com/assert-never/-/assert-never-1.2.1.tgz#11f0e363bf146205fb08193b5c7b90f4d1cf44fe"
211 | integrity sha512-TaTivMB6pYI1kXwrFlEhLeGfOqoDNdTxjCdwRfFFkEA30Eu+k48W34nlok2EYWJfFFzqaEmichdNM7th6M5HNw==
212 |
213 | at-least-node@^1.0.0:
214 | version "1.0.0"
215 | resolved "https://registry.yarnpkg.com/at-least-node/-/at-least-node-1.0.0.tgz#602cd4b46e844ad4effc92a8011a3c46e0238dc2"
216 | integrity sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==
217 |
218 | axios@^0.21.1, axios@^0.21.4:
219 | version "0.21.4"
220 | resolved "https://registry.yarnpkg.com/axios/-/axios-0.21.4.tgz#c67b90dc0568e5c1cf2b0b858c43ba28e2eda575"
221 | integrity sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg==
222 | dependencies:
223 | follow-redirects "^1.14.0"
224 |
225 | axios@^0.24.0:
226 | version "0.24.0"
227 | resolved "https://registry.yarnpkg.com/axios/-/axios-0.24.0.tgz#804e6fa1e4b9c5288501dd9dff56a7a0940d20d6"
228 | integrity sha512-Q6cWsys88HoPgAaFAVUb0WpPk0O8iTeisR9IMqy9G8AbO4NlpVknrnQS03zzF9PGAWgO3cgletO3VjV/P7VztA==
229 | dependencies:
230 | follow-redirects "^1.14.4"
231 |
232 | babel-walk@3.0.0-canary-5:
233 | version "3.0.0-canary-5"
234 | resolved "https://registry.yarnpkg.com/babel-walk/-/babel-walk-3.0.0-canary-5.tgz#f66ecd7298357aee44955f235a6ef54219104b11"
235 | integrity sha512-GAwkz0AihzY5bkwIY5QDR+LvsRQgB/B+1foMPvi0FZPMl5fjD7ICiznUiBdLYMH1QYe6vqu4gWYytZOccLouFw==
236 | dependencies:
237 | "@babel/types" "^7.9.6"
238 |
239 | bytes@3.1.1:
240 | version "3.1.1"
241 | resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.1.tgz#3f018291cb4cbad9accb6e6970bca9c8889e879a"
242 | integrity sha512-dWe4nWO/ruEOY7HkUJ5gFt1DCFV9zPRoJr8pV0/ASQermOZjtq8jMjOprC0Kd10GLN+l7xaUPvxzJFWtxGu8Fg==
243 |
244 | cache-content-type@^1.0.0:
245 | version "1.0.1"
246 | resolved "https://registry.yarnpkg.com/cache-content-type/-/cache-content-type-1.0.1.tgz#035cde2b08ee2129f4a8315ea8f00a00dba1453c"
247 | integrity sha512-IKufZ1o4Ut42YUrZSo8+qnMTrFuKkvyoLXUywKz9GJ5BrhOFGhLdkx9sG4KAnVvbY6kEcSFjLQul+DVmBm2bgA==
248 | dependencies:
249 | mime-types "^2.1.18"
250 | ylru "^1.2.0"
251 |
252 | call-bind@^1.0.0, call-bind@^1.0.2:
253 | version "1.0.2"
254 | resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.2.tgz#b1d4e89e688119c3c9a903ad30abb2f6a919be3c"
255 | integrity sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==
256 | dependencies:
257 | function-bind "^1.1.1"
258 | get-intrinsic "^1.0.2"
259 |
260 | character-parser@^2.2.0:
261 | version "2.2.0"
262 | resolved "https://registry.yarnpkg.com/character-parser/-/character-parser-2.2.0.tgz#c7ce28f36d4bcd9744e5ffc2c5fcde1c73261fc0"
263 | integrity sha1-x84o821LzZdE5f/CxfzeHHMmH8A=
264 | dependencies:
265 | is-regex "^1.0.3"
266 |
267 | co-body@^6.0.0:
268 | version "6.1.0"
269 | resolved "https://registry.yarnpkg.com/co-body/-/co-body-6.1.0.tgz#d87a8efc3564f9bfe3aced8ef5cd04c7a8766547"
270 | integrity sha512-m7pOT6CdLN7FuXUcpuz/8lfQ/L77x8SchHCF4G0RBTJO20Wzmhn5Sp4/5WsKy8OSpifBSUrmg83qEqaDHdyFuQ==
271 | dependencies:
272 | inflation "^2.0.0"
273 | qs "^6.5.2"
274 | raw-body "^2.3.3"
275 | type-is "^1.6.16"
276 |
277 | co@^4.6.0:
278 | version "4.6.0"
279 | resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184"
280 | integrity sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=
281 |
282 | commander@^7.1.0:
283 | version "7.2.0"
284 | resolved "https://registry.yarnpkg.com/commander/-/commander-7.2.0.tgz#a36cb57d0b501ce108e4d20559a150a391d97ab7"
285 | integrity sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==
286 |
287 | constantinople@^4.0.1:
288 | version "4.0.1"
289 | resolved "https://registry.yarnpkg.com/constantinople/-/constantinople-4.0.1.tgz#0def113fa0e4dc8de83331a5cf79c8b325213151"
290 | integrity sha512-vCrqcSIq4//Gx74TXXCGnHpulY1dskqLTFGDmhrGxzeXL8lF8kvXv6mpNWlJj1uD4DW23D4ljAqbY4RRaaUZIw==
291 | dependencies:
292 | "@babel/parser" "^7.6.0"
293 | "@babel/types" "^7.6.1"
294 |
295 | content-disposition@~0.5.2:
296 | version "0.5.3"
297 | resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.3.tgz#e130caf7e7279087c5616c2007d0485698984fbd"
298 | integrity sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==
299 | dependencies:
300 | safe-buffer "5.1.2"
301 |
302 | content-type@^1.0.4:
303 | version "1.0.4"
304 | resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.4.tgz#e138cc75e040c727b1966fe5e5f8c9aee256fe3b"
305 | integrity sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==
306 |
307 | cookies@~0.8.0:
308 | version "0.8.0"
309 | resolved "https://registry.yarnpkg.com/cookies/-/cookies-0.8.0.tgz#1293ce4b391740a8406e3c9870e828c4b54f3f90"
310 | integrity sha512-8aPsApQfebXnuI+537McwYsDtjVxGm8gTIzQI3FDW6t5t/DAhERxtnbEPN/8RX+uZthoz4eCOgloXaE5cYyNow==
311 | dependencies:
312 | depd "~2.0.0"
313 | keygrip "~1.1.0"
314 |
315 | copy-to@^2.0.1:
316 | version "2.0.1"
317 | resolved "https://registry.yarnpkg.com/copy-to/-/copy-to-2.0.1.tgz#2680fbb8068a48d08656b6098092bdafc906f4a5"
318 | integrity sha1-JoD7uAaKSNCGVrYJgJK9r8kG9KU=
319 |
320 | debug@^4.1.1, debug@^4.3.2:
321 | version "4.3.3"
322 | resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.3.tgz#04266e0b70a98d4462e6e288e38259213332b664"
323 | integrity sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==
324 | dependencies:
325 | ms "2.1.2"
326 |
327 | deep-equal@~1.0.1:
328 | version "1.0.1"
329 | resolved "https://registry.yarnpkg.com/deep-equal/-/deep-equal-1.0.1.tgz#f5d260292b660e084eff4cdbc9f08ad3247448b5"
330 | integrity sha1-9dJgKStmDghO/0zbyfCK0yR0SLU=
331 |
332 | delegates@^1.0.0:
333 | version "1.0.0"
334 | resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a"
335 | integrity sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=
336 |
337 | depd@^2.0.0, depd@~2.0.0:
338 | version "2.0.0"
339 | resolved "https://registry.yarnpkg.com/depd/-/depd-2.0.0.tgz#b696163cc757560d09cf22cc8fad1571b79e76df"
340 | integrity sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==
341 |
342 | depd@~1.1.2:
343 | version "1.1.2"
344 | resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9"
345 | integrity sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=
346 |
347 | destroy@^1.0.4:
348 | version "1.0.4"
349 | resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.0.4.tgz#978857442c44749e4206613e37946205826abd80"
350 | integrity sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=
351 |
352 | doctypes@^1.1.0:
353 | version "1.1.0"
354 | resolved "https://registry.yarnpkg.com/doctypes/-/doctypes-1.1.0.tgz#ea80b106a87538774e8a3a4a5afe293de489e0a9"
355 | integrity sha1-6oCxBqh1OHdOijpKWv4pPeSJ4Kk=
356 |
357 | ee-first@1.1.1:
358 | version "1.1.1"
359 | resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d"
360 | integrity sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=
361 |
362 | encodeurl@^1.0.2:
363 | version "1.0.2"
364 | resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59"
365 | integrity sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=
366 |
367 | escape-html@^1.0.3:
368 | version "1.0.3"
369 | resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988"
370 | integrity sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=
371 |
372 | fastest-levenshtein@^1.0.12:
373 | version "1.0.12"
374 | resolved "https://registry.yarnpkg.com/fastest-levenshtein/-/fastest-levenshtein-1.0.12.tgz#9990f7d3a88cc5a9ffd1f1745745251700d497e2"
375 | integrity sha512-On2N+BpYJ15xIC974QNVuYGMOlEVt4s0EOI3wwMqOmK1fdDY+FN/zltPV8vosq4ad4c/gJ1KHScUn/6AWIgiow==
376 |
377 | follow-redirects@^1.14.0, follow-redirects@^1.14.4:
378 | version "1.14.5"
379 | resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.14.5.tgz#f09a5848981d3c772b5392309778523f8d85c381"
380 | integrity sha512-wtphSXy7d4/OR+MvIFbCVBDzZ5520qV8XfPklSN5QtxuMUJZ+b0Wnst1e1lCDocfzuCkHqj8k0FpZqO+UIaKNA==
381 |
382 | fresh@~0.5.2:
383 | version "0.5.2"
384 | resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7"
385 | integrity sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=
386 |
387 | fs-extra@^9.1.0:
388 | version "9.1.0"
389 | resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-9.1.0.tgz#5954460c764a8da2094ba3554bf839e6b9a7c86d"
390 | integrity sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==
391 | dependencies:
392 | at-least-node "^1.0.0"
393 | graceful-fs "^4.2.0"
394 | jsonfile "^6.0.1"
395 | universalify "^2.0.0"
396 |
397 | function-bind@^1.1.1:
398 | version "1.1.1"
399 | resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d"
400 | integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==
401 |
402 | genshin-gacha-kit@^1.1.0:
403 | version "1.1.0"
404 | resolved "https://registry.yarnpkg.com/genshin-gacha-kit/-/genshin-gacha-kit-1.1.0.tgz#dd1b73e69e7c04bd7b94e4e2113bd05b5229a93b"
405 | integrity sha512-xQ2tRLjSzcGD5FA2RTJZ35oDjenuvJr+eBvvet6TN9dkedLDydYqq73hVshRXvaYcVqUKbX543MvxYBAVEhD+A==
406 | dependencies:
407 | axios "^0.21.1"
408 | tslib "^2.2.0"
409 |
410 | get-intrinsic@^1.0.2:
411 | version "1.1.1"
412 | resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.1.1.tgz#15f59f376f855c446963948f0d24cd3637b4abc6"
413 | integrity sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==
414 | dependencies:
415 | function-bind "^1.1.1"
416 | has "^1.0.3"
417 | has-symbols "^1.0.1"
418 |
419 | graceful-fs@^4.1.6, graceful-fs@^4.2.0:
420 | version "4.2.8"
421 | resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.8.tgz#e412b8d33f5e006593cbd3cee6df9f2cebbe802a"
422 | integrity sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg==
423 |
424 | has-flag@^4.0.0:
425 | version "4.0.0"
426 | resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b"
427 | integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==
428 |
429 | has-symbols@^1.0.1, has-symbols@^1.0.2:
430 | version "1.0.2"
431 | resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.2.tgz#165d3070c00309752a1236a479331e3ac56f1423"
432 | integrity sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==
433 |
434 | has-tostringtag@^1.0.0:
435 | version "1.0.0"
436 | resolved "https://registry.yarnpkg.com/has-tostringtag/-/has-tostringtag-1.0.0.tgz#7e133818a7d394734f941e73c3d3f9291e658b25"
437 | integrity sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==
438 | dependencies:
439 | has-symbols "^1.0.2"
440 |
441 | has@^1.0.3:
442 | version "1.0.3"
443 | resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796"
444 | integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==
445 | dependencies:
446 | function-bind "^1.1.1"
447 |
448 | http-assert@^1.3.0:
449 | version "1.5.0"
450 | resolved "https://registry.yarnpkg.com/http-assert/-/http-assert-1.5.0.tgz#c389ccd87ac16ed2dfa6246fd73b926aa00e6b8f"
451 | integrity sha512-uPpH7OKX4H25hBmU6G1jWNaqJGpTXxey+YOUizJUAgu0AjLUeC8D73hTrhvDS5D+GJN1DN1+hhc/eF/wpxtp0w==
452 | dependencies:
453 | deep-equal "~1.0.1"
454 | http-errors "~1.8.0"
455 |
456 | http-errors@1.8.1, http-errors@^1.6.3, http-errors@^1.7.3, http-errors@~1.8.0:
457 | version "1.8.1"
458 | resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.8.1.tgz#7c3f28577cbc8a207388455dbd62295ed07bd68c"
459 | integrity sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g==
460 | dependencies:
461 | depd "~1.1.2"
462 | inherits "2.0.4"
463 | setprototypeof "1.2.0"
464 | statuses ">= 1.5.0 < 2"
465 | toidentifier "1.0.1"
466 |
467 | iconv-lite@0.4.24:
468 | version "0.4.24"
469 | resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b"
470 | integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==
471 | dependencies:
472 | safer-buffer ">= 2.1.2 < 3"
473 |
474 | inflation@^2.0.0:
475 | version "2.0.0"
476 | resolved "https://registry.yarnpkg.com/inflation/-/inflation-2.0.0.tgz#8b417e47c28f925a45133d914ca1fd389107f30f"
477 | integrity sha1-i0F+R8KPklpFEz2RTKH9OJEH8w8=
478 |
479 | inherits@2.0.4:
480 | version "2.0.4"
481 | resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c"
482 | integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==
483 |
484 | is-core-module@^2.2.0:
485 | version "2.8.0"
486 | resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.8.0.tgz#0321336c3d0925e497fd97f5d95cb114a5ccd548"
487 | integrity sha512-vd15qHsaqrRL7dtH6QNuy0ndJmRDrS9HAM1CAiSifNUFv4x1a0CCVsj18hJ1mShxIG6T2i1sO78MkP56r0nYRw==
488 | dependencies:
489 | has "^1.0.3"
490 |
491 | is-expression@^4.0.0:
492 | version "4.0.0"
493 | resolved "https://registry.yarnpkg.com/is-expression/-/is-expression-4.0.0.tgz#c33155962abf21d0afd2552514d67d2ec16fd2ab"
494 | integrity sha512-zMIXX63sxzG3XrkHkrAPvm/OVZVSCPNkwMHU8oTX7/U3AL78I0QXCEICXUM13BIa8TYGZ68PiTKfQz3yaTNr4A==
495 | dependencies:
496 | acorn "^7.1.1"
497 | object-assign "^4.1.1"
498 |
499 | is-generator-function@^1.0.7:
500 | version "1.0.10"
501 | resolved "https://registry.yarnpkg.com/is-generator-function/-/is-generator-function-1.0.10.tgz#f1558baf1ac17e0deea7c0415c438351ff2b3c72"
502 | integrity sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==
503 | dependencies:
504 | has-tostringtag "^1.0.0"
505 |
506 | is-promise@^2.0.0:
507 | version "2.2.2"
508 | resolved "https://registry.yarnpkg.com/is-promise/-/is-promise-2.2.2.tgz#39ab959ccbf9a774cf079f7b40c7a26f763135f1"
509 | integrity sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ==
510 |
511 | is-regex@^1.0.3:
512 | version "1.1.4"
513 | resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.1.4.tgz#eef5663cd59fa4c0ae339505323df6854bb15958"
514 | integrity sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==
515 | dependencies:
516 | call-bind "^1.0.2"
517 | has-tostringtag "^1.0.0"
518 |
519 | js-stringify@^1.0.2:
520 | version "1.0.2"
521 | resolved "https://registry.yarnpkg.com/js-stringify/-/js-stringify-1.0.2.tgz#1736fddfd9724f28a3682adc6230ae7e4e9679db"
522 | integrity sha1-Fzb939lyTyijaCrcYjCufk6Weds=
523 |
524 | jsonfile@^6.0.1:
525 | version "6.1.0"
526 | resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-6.1.0.tgz#bc55b2634793c679ec6403094eb13698a6ec0aae"
527 | integrity sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==
528 | dependencies:
529 | universalify "^2.0.0"
530 | optionalDependencies:
531 | graceful-fs "^4.1.6"
532 |
533 | jstransformer@1.0.0:
534 | version "1.0.0"
535 | resolved "https://registry.yarnpkg.com/jstransformer/-/jstransformer-1.0.0.tgz#ed8bf0921e2f3f1ed4d5c1a44f68709ed24722c3"
536 | integrity sha1-7Yvwkh4vPx7U1cGkT2hwntJHIsM=
537 | dependencies:
538 | is-promise "^2.0.0"
539 | promise "^7.0.1"
540 |
541 | keygrip@~1.1.0:
542 | version "1.1.0"
543 | resolved "https://registry.yarnpkg.com/keygrip/-/keygrip-1.1.0.tgz#871b1681d5e159c62a445b0c74b615e0917e7226"
544 | integrity sha512-iYSchDJ+liQ8iwbSI2QqsQOvqv58eJCEanyJPJi+Khyu8smkcKSFUCbPwzFcL7YVtZ6eONjqRX/38caJ7QjRAQ==
545 | dependencies:
546 | tsscmp "1.0.6"
547 |
548 | koa-bodyparser@^4.3.0:
549 | version "4.3.0"
550 | resolved "https://registry.yarnpkg.com/koa-bodyparser/-/koa-bodyparser-4.3.0.tgz#274c778555ff48fa221ee7f36a9fbdbace22759a"
551 | integrity sha512-uyV8G29KAGwZc4q/0WUAjH+Tsmuv9ImfBUF2oZVyZtaeo0husInagyn/JH85xMSxM0hEk/mbCII5ubLDuqW/Rw==
552 | dependencies:
553 | co-body "^6.0.0"
554 | copy-to "^2.0.1"
555 |
556 | koa-compose@^4.1.0:
557 | version "4.1.0"
558 | resolved "https://registry.yarnpkg.com/koa-compose/-/koa-compose-4.1.0.tgz#507306b9371901db41121c812e923d0d67d3e877"
559 | integrity sha512-8ODW8TrDuMYvXRwra/Kh7/rJo9BtOfPc6qO8eAfC80CnCvSjSl0bkRM24X6/XBBEyj0v1nRUQ1LyOy3dbqOWXw==
560 |
561 | koa-convert@^2.0.0:
562 | version "2.0.0"
563 | resolved "https://registry.yarnpkg.com/koa-convert/-/koa-convert-2.0.0.tgz#86a0c44d81d40551bae22fee6709904573eea4f5"
564 | integrity sha512-asOvN6bFlSnxewce2e/DK3p4tltyfC4VM7ZwuTuepI7dEQVcvpyFuBcEARu1+Hxg8DIwytce2n7jrZtRlPrARA==
565 | dependencies:
566 | co "^4.6.0"
567 | koa-compose "^4.1.0"
568 |
569 | koa@^2.13.1:
570 | version "2.13.4"
571 | resolved "https://registry.yarnpkg.com/koa/-/koa-2.13.4.tgz#ee5b0cb39e0b8069c38d115139c774833d32462e"
572 | integrity sha512-43zkIKubNbnrULWlHdN5h1g3SEKXOEzoAlRsHOTFpnlDu8JlAOZSMJBLULusuXRequboiwJcj5vtYXKB3k7+2g==
573 | dependencies:
574 | accepts "^1.3.5"
575 | cache-content-type "^1.0.0"
576 | content-disposition "~0.5.2"
577 | content-type "^1.0.4"
578 | cookies "~0.8.0"
579 | debug "^4.3.2"
580 | delegates "^1.0.0"
581 | depd "^2.0.0"
582 | destroy "^1.0.4"
583 | encodeurl "^1.0.2"
584 | escape-html "^1.0.3"
585 | fresh "~0.5.2"
586 | http-assert "^1.3.0"
587 | http-errors "^1.6.3"
588 | is-generator-function "^1.0.7"
589 | koa-compose "^4.1.0"
590 | koa-convert "^2.0.0"
591 | on-finished "^2.3.0"
592 | only "~0.0.2"
593 | parseurl "^1.3.2"
594 | statuses "^1.5.0"
595 | type-is "^1.6.16"
596 | vary "^1.1.2"
597 |
598 | koishi-core@^3.13.1:
599 | version "3.14.2"
600 | resolved "https://registry.yarnpkg.com/koishi-core/-/koishi-core-3.14.2.tgz#036b11f592a9c7c0c6324ad7dc5a5c675d502ffb"
601 | integrity sha512-32Zh35DL+ok8DNeNri4amIpt6Njf2lQ+Zgt5wNH5nq5BdUvPSEc4jAQhtcwxnrGvdVrl8n5QIuCZfkdY5tMk6w==
602 | dependencies:
603 | "@koa/router" "^10.1.1"
604 | "@types/koa__router" "^8.0.8"
605 | "@types/lru-cache" "^5.1.1"
606 | "@types/ws" "^7.4.7"
607 | axios "^0.21.4"
608 | fastest-levenshtein "^1.0.12"
609 | koa "^2.13.1"
610 | koa-bodyparser "^4.3.0"
611 | koishi-utils "^4.3.0"
612 | lru-cache "^6.0.0"
613 |
614 | koishi-utils@^4.3.0:
615 | version "4.3.0"
616 | resolved "https://registry.yarnpkg.com/koishi-utils/-/koishi-utils-4.3.0.tgz#14bd29033516f6527f3f04f664c5ec1ee1244d82"
617 | integrity sha512-MV799odIPx2xWIcI4kIFFUmZotKUwejBo/ChYTZ3reQNZ0VGpvUghA4+oMm4m6qOgXlJsUiUc84kbSwOPrYWmw==
618 | dependencies:
619 | supports-color "^8.1.0"
620 |
621 | lru-cache@^6.0.0:
622 | version "6.0.0"
623 | resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94"
624 | integrity sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==
625 | dependencies:
626 | yallist "^4.0.0"
627 |
628 | media-typer@0.3.0:
629 | version "0.3.0"
630 | resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748"
631 | integrity sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=
632 |
633 | methods@^1.1.2:
634 | version "1.1.2"
635 | resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee"
636 | integrity sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=
637 |
638 | mime-db@1.51.0:
639 | version "1.51.0"
640 | resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.51.0.tgz#d9ff62451859b18342d960850dc3cfb77e63fb0c"
641 | integrity sha512-5y8A56jg7XVQx2mbv1lu49NR4dokRnhZYTtL+KGfaa27uq4pSTXkwQkFJl4pkRMyNFz/EtYDSkiiEHx3F7UN6g==
642 |
643 | mime-types@^2.1.18, mime-types@~2.1.24:
644 | version "2.1.34"
645 | resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.34.tgz#5a712f9ec1503511a945803640fafe09d3793c24"
646 | integrity sha512-6cP692WwGIs9XXdOO4++N+7qjqv0rqxxVvJ3VHPh/Sc9mVZcQP+ZGhkKiTvWMQRr2tbHkJP/Yn7Y0npb3ZBs4A==
647 | dependencies:
648 | mime-db "1.51.0"
649 |
650 | ms@2.1.2:
651 | version "2.1.2"
652 | resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009"
653 | integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==
654 |
655 | negotiator@0.6.2:
656 | version "0.6.2"
657 | resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.2.tgz#feacf7ccf525a77ae9634436a64883ffeca346fb"
658 | integrity sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==
659 |
660 | object-assign@^4.1.1:
661 | version "4.1.1"
662 | resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863"
663 | integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=
664 |
665 | object-inspect@^1.9.0:
666 | version "1.11.1"
667 | resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.11.1.tgz#d4bd7d7de54b9a75599f59a00bd698c1f1c6549b"
668 | integrity sha512-If7BjFlpkzzBeV1cqgT3OSWT3azyoxDGajR+iGnFBfVV2EWyDyWaZZW2ERDjUaY2QM8i5jI3Sj7mhsM4DDAqWA==
669 |
670 | on-finished@^2.3.0:
671 | version "2.3.0"
672 | resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.3.0.tgz#20f1336481b083cd75337992a16971aa2d906947"
673 | integrity sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=
674 | dependencies:
675 | ee-first "1.1.1"
676 |
677 | only@~0.0.2:
678 | version "0.0.2"
679 | resolved "https://registry.yarnpkg.com/only/-/only-0.0.2.tgz#2afde84d03e50b9a8edc444e30610a70295edfb4"
680 | integrity sha1-Kv3oTQPlC5qO3EROMGEKcCle37Q=
681 |
682 | parseurl@^1.3.2:
683 | version "1.3.3"
684 | resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4"
685 | integrity sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==
686 |
687 | path-parse@^1.0.6:
688 | version "1.0.7"
689 | resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735"
690 | integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==
691 |
692 | path-to-regexp@^6.1.0:
693 | version "6.2.0"
694 | resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-6.2.0.tgz#f7b3803336104c346889adece614669230645f38"
695 | integrity sha512-f66KywYG6+43afgE/8j/GoiNyygk/bnoCbps++3ErRKsIYkGGupyv07R2Ok5m9i67Iqc+T2g1eAUGUPzWhYTyg==
696 |
697 | promise@^7.0.1:
698 | version "7.3.1"
699 | resolved "https://registry.yarnpkg.com/promise/-/promise-7.3.1.tgz#064b72602b18f90f29192b8b1bc418ffd1ebd3bf"
700 | integrity sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg==
701 | dependencies:
702 | asap "~2.0.3"
703 |
704 | pug-attrs@^3.0.0:
705 | version "3.0.0"
706 | resolved "https://registry.yarnpkg.com/pug-attrs/-/pug-attrs-3.0.0.tgz#b10451e0348165e31fad1cc23ebddd9dc7347c41"
707 | integrity sha512-azINV9dUtzPMFQktvTXciNAfAuVh/L/JCl0vtPCwvOA21uZrC08K/UnmrL+SXGEVc1FwzjW62+xw5S/uaLj6cA==
708 | dependencies:
709 | constantinople "^4.0.1"
710 | js-stringify "^1.0.2"
711 | pug-runtime "^3.0.0"
712 |
713 | pug-code-gen@^3.0.2:
714 | version "3.0.2"
715 | resolved "https://registry.yarnpkg.com/pug-code-gen/-/pug-code-gen-3.0.2.tgz#ad190f4943133bf186b60b80de483100e132e2ce"
716 | integrity sha512-nJMhW16MbiGRiyR4miDTQMRWDgKplnHyeLvioEJYbk1RsPI3FuA3saEP8uwnTb2nTJEKBU90NFVWJBk4OU5qyg==
717 | dependencies:
718 | constantinople "^4.0.1"
719 | doctypes "^1.1.0"
720 | js-stringify "^1.0.2"
721 | pug-attrs "^3.0.0"
722 | pug-error "^2.0.0"
723 | pug-runtime "^3.0.0"
724 | void-elements "^3.1.0"
725 | with "^7.0.0"
726 |
727 | pug-error@^2.0.0:
728 | version "2.0.0"
729 | resolved "https://registry.yarnpkg.com/pug-error/-/pug-error-2.0.0.tgz#5c62173cb09c34de2a2ce04f17b8adfec74d8ca5"
730 | integrity sha512-sjiUsi9M4RAGHktC1drQfCr5C5eriu24Lfbt4s+7SykztEOwVZtbFk1RRq0tzLxcMxMYTBR+zMQaG07J/btayQ==
731 |
732 | pug-filters@^4.0.0:
733 | version "4.0.0"
734 | resolved "https://registry.yarnpkg.com/pug-filters/-/pug-filters-4.0.0.tgz#d3e49af5ba8472e9b7a66d980e707ce9d2cc9b5e"
735 | integrity sha512-yeNFtq5Yxmfz0f9z2rMXGw/8/4i1cCFecw/Q7+D0V2DdtII5UvqE12VaZ2AY7ri6o5RNXiweGH79OCq+2RQU4A==
736 | dependencies:
737 | constantinople "^4.0.1"
738 | jstransformer "1.0.0"
739 | pug-error "^2.0.0"
740 | pug-walk "^2.0.0"
741 | resolve "^1.15.1"
742 |
743 | pug-lexer@^5.0.1:
744 | version "5.0.1"
745 | resolved "https://registry.yarnpkg.com/pug-lexer/-/pug-lexer-5.0.1.tgz#ae44628c5bef9b190b665683b288ca9024b8b0d5"
746 | integrity sha512-0I6C62+keXlZPZkOJeVam9aBLVP2EnbeDw3An+k0/QlqdwH6rv8284nko14Na7c0TtqtogfWXcRoFE4O4Ff20w==
747 | dependencies:
748 | character-parser "^2.2.0"
749 | is-expression "^4.0.0"
750 | pug-error "^2.0.0"
751 |
752 | pug-linker@^4.0.0:
753 | version "4.0.0"
754 | resolved "https://registry.yarnpkg.com/pug-linker/-/pug-linker-4.0.0.tgz#12cbc0594fc5a3e06b9fc59e6f93c146962a7708"
755 | integrity sha512-gjD1yzp0yxbQqnzBAdlhbgoJL5qIFJw78juN1NpTLt/mfPJ5VgC4BvkoD3G23qKzJtIIXBbcCt6FioLSFLOHdw==
756 | dependencies:
757 | pug-error "^2.0.0"
758 | pug-walk "^2.0.0"
759 |
760 | pug-load@^3.0.0:
761 | version "3.0.0"
762 | resolved "https://registry.yarnpkg.com/pug-load/-/pug-load-3.0.0.tgz#9fd9cda52202b08adb11d25681fb9f34bd41b662"
763 | integrity sha512-OCjTEnhLWZBvS4zni/WUMjH2YSUosnsmjGBB1An7CsKQarYSWQ0GCVyd4eQPMFJqZ8w9xgs01QdiZXKVjk92EQ==
764 | dependencies:
765 | object-assign "^4.1.1"
766 | pug-walk "^2.0.0"
767 |
768 | pug-parser@^6.0.0:
769 | version "6.0.0"
770 | resolved "https://registry.yarnpkg.com/pug-parser/-/pug-parser-6.0.0.tgz#a8fdc035863a95b2c1dc5ebf4ecf80b4e76a1260"
771 | integrity sha512-ukiYM/9cH6Cml+AOl5kETtM9NR3WulyVP2y4HOU45DyMim1IeP/OOiyEWRr6qk5I5klpsBnbuHpwKmTx6WURnw==
772 | dependencies:
773 | pug-error "^2.0.0"
774 | token-stream "1.0.0"
775 |
776 | pug-runtime@^3.0.0, pug-runtime@^3.0.1:
777 | version "3.0.1"
778 | resolved "https://registry.yarnpkg.com/pug-runtime/-/pug-runtime-3.0.1.tgz#f636976204723f35a8c5f6fad6acda2a191b83d7"
779 | integrity sha512-L50zbvrQ35TkpHwv0G6aLSuueDRwc/97XdY8kL3tOT0FmhgG7UypU3VztfV/LATAvmUfYi4wNxSajhSAeNN+Kg==
780 |
781 | pug-strip-comments@^2.0.0:
782 | version "2.0.0"
783 | resolved "https://registry.yarnpkg.com/pug-strip-comments/-/pug-strip-comments-2.0.0.tgz#f94b07fd6b495523330f490a7f554b4ff876303e"
784 | integrity sha512-zo8DsDpH7eTkPHCXFeAk1xZXJbyoTfdPlNR0bK7rpOMuhBYb0f5qUVCO1xlsitYd3w5FQTK7zpNVKb3rZoUrrQ==
785 | dependencies:
786 | pug-error "^2.0.0"
787 |
788 | pug-walk@^2.0.0:
789 | version "2.0.0"
790 | resolved "https://registry.yarnpkg.com/pug-walk/-/pug-walk-2.0.0.tgz#417aabc29232bb4499b5b5069a2b2d2a24d5f5fe"
791 | integrity sha512-yYELe9Q5q9IQhuvqsZNwA5hfPkMJ8u92bQLIMcsMxf/VADjNtEYptU+inlufAFYcWdHlwNfZOEnOOQrZrcyJCQ==
792 |
793 | pug@^3.0.2:
794 | version "3.0.2"
795 | resolved "https://registry.yarnpkg.com/pug/-/pug-3.0.2.tgz#f35c7107343454e43bc27ae0ff76c731b78ea535"
796 | integrity sha512-bp0I/hiK1D1vChHh6EfDxtndHji55XP/ZJKwsRqrz6lRia6ZC2OZbdAymlxdVFwd1L70ebrVJw4/eZ79skrIaw==
797 | dependencies:
798 | pug-code-gen "^3.0.2"
799 | pug-filters "^4.0.0"
800 | pug-lexer "^5.0.1"
801 | pug-linker "^4.0.0"
802 | pug-load "^3.0.0"
803 | pug-parser "^6.0.0"
804 | pug-runtime "^3.0.1"
805 | pug-strip-comments "^2.0.0"
806 |
807 | qs@^6.5.2:
808 | version "6.10.2"
809 | resolved "https://registry.yarnpkg.com/qs/-/qs-6.10.2.tgz#c1431bea37fc5b24c5bdbafa20f16bdf2a4b9ffe"
810 | integrity sha512-mSIdjzqznWgfd4pMii7sHtaYF8rx8861hBO80SraY5GT0XQibWZWJSid0avzHGkDIZLImux2S5mXO0Hfct2QCw==
811 | dependencies:
812 | side-channel "^1.0.4"
813 |
814 | raw-body@^2.3.3:
815 | version "2.4.2"
816 | resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.4.2.tgz#baf3e9c21eebced59dd6533ac872b71f7b61cb32"
817 | integrity sha512-RPMAFUJP19WIet/99ngh6Iv8fzAbqum4Li7AD6DtGaW2RpMB/11xDoalPiJMTbu6I3hkbMVkATvZrqb9EEqeeQ==
818 | dependencies:
819 | bytes "3.1.1"
820 | http-errors "1.8.1"
821 | iconv-lite "0.4.24"
822 | unpipe "1.0.0"
823 |
824 | resolve@^1.15.1:
825 | version "1.20.0"
826 | resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.20.0.tgz#629a013fb3f70755d6f0b7935cc1c2c5378b1975"
827 | integrity sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==
828 | dependencies:
829 | is-core-module "^2.2.0"
830 | path-parse "^1.0.6"
831 |
832 | safe-buffer@5.1.2:
833 | version "5.1.2"
834 | resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d"
835 | integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==
836 |
837 | "safer-buffer@>= 2.1.2 < 3":
838 | version "2.1.2"
839 | resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a"
840 | integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==
841 |
842 | setprototypeof@1.2.0:
843 | version "1.2.0"
844 | resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.2.0.tgz#66c9a24a73f9fc28cbe66b09fed3d33dcaf1b424"
845 | integrity sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==
846 |
847 | side-channel@^1.0.4:
848 | version "1.0.4"
849 | resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.4.tgz#efce5c8fdc104ee751b25c58d4290011fa5ea2cf"
850 | integrity sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==
851 | dependencies:
852 | call-bind "^1.0.0"
853 | get-intrinsic "^1.0.2"
854 | object-inspect "^1.9.0"
855 |
856 | "statuses@>= 1.5.0 < 2", statuses@^1.5.0:
857 | version "1.5.0"
858 | resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c"
859 | integrity sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=
860 |
861 | supports-color@^8.1.0:
862 | version "8.1.1"
863 | resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-8.1.1.tgz#cd6fc17e28500cff56c1b86c0a7fd4a54a73005c"
864 | integrity sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==
865 | dependencies:
866 | has-flag "^4.0.0"
867 |
868 | to-fast-properties@^2.0.0:
869 | version "2.0.0"
870 | resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e"
871 | integrity sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=
872 |
873 | toidentifier@1.0.1:
874 | version "1.0.1"
875 | resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.1.tgz#3be34321a88a820ed1bd80dfaa33e479fbb8dd35"
876 | integrity sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==
877 |
878 | token-stream@1.0.0:
879 | version "1.0.0"
880 | resolved "https://registry.yarnpkg.com/token-stream/-/token-stream-1.0.0.tgz#cc200eab2613f4166d27ff9afc7ca56d49df6eb4"
881 | integrity sha1-zCAOqyYT9BZtJ/+a/HylbUnfbrQ=
882 |
883 | tslib@^2.2.0, tslib@^2.3.1:
884 | version "2.3.1"
885 | resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.3.1.tgz#e8a335add5ceae51aa261d32a490158ef042ef01"
886 | integrity sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==
887 |
888 | tsscmp@1.0.6:
889 | version "1.0.6"
890 | resolved "https://registry.yarnpkg.com/tsscmp/-/tsscmp-1.0.6.tgz#85b99583ac3589ec4bfef825b5000aa911d605eb"
891 | integrity sha512-LxhtAkPDTkVCMQjt2h6eBVY28KCjikZqZfMcC15YBeNjkgUpdCfBu5HoiOTDu86v6smE8yOjyEktJ8hlbANHQA==
892 |
893 | type-is@^1.6.16:
894 | version "1.6.18"
895 | resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.18.tgz#4e552cd05df09467dcbc4ef739de89f2cf37c131"
896 | integrity sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==
897 | dependencies:
898 | media-typer "0.3.0"
899 | mime-types "~2.1.24"
900 |
901 | universalify@^2.0.0:
902 | version "2.0.0"
903 | resolved "https://registry.yarnpkg.com/universalify/-/universalify-2.0.0.tgz#75a4984efedc4b08975c5aeb73f530d02df25717"
904 | integrity sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==
905 |
906 | unpipe@1.0.0:
907 | version "1.0.0"
908 | resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec"
909 | integrity sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=
910 |
911 | vary@^1.1.2:
912 | version "1.1.2"
913 | resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc"
914 | integrity sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=
915 |
916 | void-elements@^3.1.0:
917 | version "3.1.0"
918 | resolved "https://registry.yarnpkg.com/void-elements/-/void-elements-3.1.0.tgz#614f7fbf8d801f0bb5f0661f5b2f5785750e4f09"
919 | integrity sha1-YU9/v42AHwu18GYfWy9XhXUOTwk=
920 |
921 | with@^7.0.0:
922 | version "7.0.2"
923 | resolved "https://registry.yarnpkg.com/with/-/with-7.0.2.tgz#ccee3ad542d25538a7a7a80aad212b9828495bac"
924 | integrity sha512-RNGKj82nUPg3g5ygxkQl0R937xLyho1J24ItRCBTr/m1YnZkzJy1hUiHUJrc/VlsDQzsCnInEGSg3bci0Lmd4w==
925 | dependencies:
926 | "@babel/parser" "^7.9.6"
927 | "@babel/types" "^7.9.6"
928 | assert-never "^1.2.1"
929 | babel-walk "3.0.0-canary-5"
930 |
931 | yallist@^4.0.0:
932 | version "4.0.0"
933 | resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72"
934 | integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==
935 |
936 | ylru@^1.2.0:
937 | version "1.2.1"
938 | resolved "https://registry.yarnpkg.com/ylru/-/ylru-1.2.1.tgz#f576b63341547989c1de7ba288760923b27fe84f"
939 | integrity sha512-faQrqNMzcPCHGVC2aaOINk13K+aaBDUPjGWl0teOXywElLjyVAB6Oe2jj62jHYtwsU49jXhScYbvPENK+6zAvQ==
940 |
--------------------------------------------------------------------------------