forked from bot/app
Compare commits
102 Commits
Author | SHA1 | Date | |
---|---|---|---|
980fca650b | |||
9c525141f6 | |||
3d218a0e8d | |||
db385f597b | |||
98a9d6413a | |||
a77f97fd4b | |||
e6ea1b700f | |||
596f4d06ea | |||
8e3d3b3b5d | |||
a34ad87e01 | |||
6c4c7f34cd | |||
0c859957b4 | |||
fbb9ed82ee | |||
b469c9420e | |||
aa4d930cc4 | |||
76be748160 | |||
a9dd37b8a5 | |||
5900d621f2 | |||
7442a3651b | |||
413f438689 | |||
1fc4999b09 | |||
975446a096 | |||
98cdd2f4b8 | |||
c0beec0429 | |||
614d78b3fa | |||
24b0f345e4 | |||
0ae10aa1b2 | |||
9fe7478840 | |||
|
efca0bc7b3 | ||
50c5e99b98 | |||
7415efcc90 | |||
5bb4584e6a | |||
795a6f3f76 | |||
|
fa74e08514 | ||
e6cf6e0c68 | |||
6789c16773 | |||
cdea0f8563 | |||
9df55671ac | |||
d96c6f13c1 | |||
bce1bf8704 | |||
8eb626b8da | |||
|
e6505d335b | ||
c8cb341afb | |||
e99cb88b13 | |||
|
78c3e299d0 | ||
23338437e9 | |||
f95899aebd | |||
5df10c66b6 | |||
811d1594cd | |||
c162208638 | |||
679d6597d8 | |||
f402799f28 | |||
|
60542d7426 | ||
db1fb58717 | |||
7d5675ec97 | |||
d8c50752f7 | |||
|
c674b837bb | ||
d867996072 | |||
7ef36c6933 | |||
982aae4dbf | |||
b5d3c6aaa8 | |||
5537bc32df | |||
5c0c723c5d | |||
0ed3b307d9 | |||
53a603d4ee | |||
fbf906bea7 | |||
a87e8bc3e8 | |||
a16a67dbc9 | |||
4c2231feb5 | |||
3932dd60da | |||
3c6380cb82 | |||
2612f99f35 | |||
0b4b9a6241 | |||
2d100885ee | |||
cb335720b7 | |||
dc8ad30b84 | |||
09e00652c3 | |||
b5b15c82f8 | |||
72e71124b8 | |||
d2be2acc95 | |||
d95614e960 | |||
dad9482d7a | |||
fff5d09ad9 | |||
e6ffd1fcc0 | |||
a97747b7c4 | |||
1921dcd023 | |||
18af1d00bd | |||
30cdc1da23 | |||
|
bb84958ce4 | ||
|
44de3fd00a | ||
39b1920532 | |||
aa591ec29e | |||
310c3f065d | |||
2311ef82c3 | |||
b4b931fc95 | |||
d1b887fcaa | |||
5a2990770c | |||
1d0f0a2539 | |||
dbc4d83b08 | |||
da905d21bd | |||
7d91079500 | |||
81a006a308 |
1
.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
1
.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
blank_issues_enabled: false
|
59
.github/ISSUE_TEMPLATE/resource_publish_en.yml
vendored
Normal file
59
.github/ISSUE_TEMPLATE/resource_publish_en.yml
vendored
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
name: Publish Resource
|
||||||
|
title: "Resource: {name}"
|
||||||
|
description: Publish the resource to the LiteyukiBot official store
|
||||||
|
labels: [ "Resource" ]
|
||||||
|
body:
|
||||||
|
- type: input
|
||||||
|
id: name
|
||||||
|
attributes:
|
||||||
|
label: Name
|
||||||
|
description: The readable name of the resource pack
|
||||||
|
placeholder: e.g. Cute UI Resource Pack
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
|
||||||
|
- type: input
|
||||||
|
id: description
|
||||||
|
attributes:
|
||||||
|
label: Description
|
||||||
|
description: A brief description of the resource
|
||||||
|
placeholder: e.g. Makes the rendering card style more beautiful
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
|
||||||
|
- type: input
|
||||||
|
id: author
|
||||||
|
attributes:
|
||||||
|
label: Author
|
||||||
|
description: The GitHub username of the author
|
||||||
|
placeholder: e.g. snowykami
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
|
||||||
|
- type: input
|
||||||
|
id: link
|
||||||
|
attributes:
|
||||||
|
label: Link
|
||||||
|
description: Direct download link of the resource pack
|
||||||
|
placeholder: e.g. https://aaa.com/r.zip
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
|
||||||
|
- type: input
|
||||||
|
id: homepage
|
||||||
|
attributes:
|
||||||
|
label: Homepage
|
||||||
|
description: Homepage of the resource pack
|
||||||
|
placeholder: e.g. https://github.com/user/repo
|
||||||
|
validations:
|
||||||
|
required: false
|
||||||
|
|
||||||
|
- type: input
|
||||||
|
id: tags
|
||||||
|
attributes:
|
||||||
|
label: Tags
|
||||||
|
description: Tags
|
||||||
|
placeholder: 'e.g. [{"label": "Tag Name", "color": "#ea5252"}]'
|
||||||
|
value: '[ { "label": "Text", "color": "#a2d8f4" } ]'
|
||||||
|
validations:
|
||||||
|
required: false
|
59
.github/ISSUE_TEMPLATE/resource_publish_zh.yml
vendored
Normal file
59
.github/ISSUE_TEMPLATE/resource_publish_zh.yml
vendored
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
name: 发布资源
|
||||||
|
title: "Resource: {name}"
|
||||||
|
description: 发布资源到轻雪机器人官方商店
|
||||||
|
labels: [ "Resource" ]
|
||||||
|
body:
|
||||||
|
- type: input
|
||||||
|
id: name
|
||||||
|
attributes:
|
||||||
|
label: 名称
|
||||||
|
description: 资源包的可读名称
|
||||||
|
placeholder: e.g. 可爱UI资源包
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
|
||||||
|
- type: input
|
||||||
|
id: description
|
||||||
|
attributes:
|
||||||
|
label: 描述
|
||||||
|
description: 资源的简短描述
|
||||||
|
placeholder: e.g. 使渲染卡片的样式更美观
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
|
||||||
|
- type: input
|
||||||
|
id: author
|
||||||
|
attributes:
|
||||||
|
label: 作者
|
||||||
|
description: 作者的github用户名
|
||||||
|
placeholder: e.g. snowykami
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
|
||||||
|
- type: input
|
||||||
|
id: link
|
||||||
|
attributes:
|
||||||
|
label: 下载链接
|
||||||
|
description: 资源包直接下载链接
|
||||||
|
placeholder: e.g. https://aaa.com/r.zip
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
|
||||||
|
- type: input
|
||||||
|
id: homepage
|
||||||
|
attributes:
|
||||||
|
label: 主页
|
||||||
|
description: 资源包主页
|
||||||
|
placeholder: e.g. https://github.com/user/repo
|
||||||
|
validations:
|
||||||
|
required: false
|
||||||
|
|
||||||
|
- type: input
|
||||||
|
id: tags
|
||||||
|
attributes:
|
||||||
|
label: 标签
|
||||||
|
description: 标签
|
||||||
|
placeholder: 'e.g. [{"label": "标签名", "color": "#ea5252"}]'
|
||||||
|
value: '[ { "label": "标签名", "color": "#a2d8f4" } ]'
|
||||||
|
validations:
|
||||||
|
required: false
|
44
.github/workflows/ISSUE_TEMPLATE.md
vendored
44
.github/workflows/ISSUE_TEMPLATE.md
vendored
@@ -1,44 +0,0 @@
|
|||||||
# 问题反馈
|
|
||||||
|
|
||||||
## **请确保**
|
|
||||||
|
|
||||||
- 已认真阅读[文档]("https://bot.liteyuki.icu"),该问题不是文档提及的或你自己操作不当造成的
|
|
||||||
- 你的问题是在最新版本的代码上测试的
|
|
||||||
- 请勿重复提交相同或类似的issue
|
|
||||||
|
|
||||||
|
|
||||||
## **描述问题**
|
|
||||||
|
|
||||||
请在此简单描述问题
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## **如何复现**
|
|
||||||
|
|
||||||
请阐述一下如何重现这个问题
|
|
||||||
### 预期
|
|
||||||
|
|
||||||
描述你期望发生的事情
|
|
||||||
|
|
||||||
### 实际
|
|
||||||
|
|
||||||
描述实际发生的事情
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## **日志或截图**
|
|
||||||
```
|
|
||||||
日志内容
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
## **设备信息**
|
|
||||||
- **系统**: [例如 Ubuntu 22.04]
|
|
||||||
- **CPU**: [例如 Intel i7-7700K]
|
|
||||||
- **内存**: [例如 16GB]
|
|
||||||
- **Python**: [例如CPython 3.10.7]
|
|
||||||
|
|
||||||
|
|
||||||
**补充内容**
|
|
||||||
|
|
||||||
可选,推荐提供`pip freeze`的输出,以及其他相关信息,以及你的建议
|
|
4
.github/workflows/deploy-docs.yml
vendored
4
.github/workflows/deploy-docs.yml
vendored
@@ -40,8 +40,8 @@ jobs:
|
|||||||
- name: Setup API markdown
|
- name: Setup API markdown
|
||||||
run: |-
|
run: |-
|
||||||
python -m pip install litedoc
|
python -m pip install litedoc
|
||||||
litedoc liteyuki -o docs/zh/dev/api -l zh-Hans -cd class -fd func -md func -vd var -cs -bu https://github.com/LiteyukiStudio/LiteyukiBot/tree/main/liteyuki/
|
litedoc liteyuki -o docs/zh/dev/api -l zh-Hans -cd class -fd func -md func -vd var -bu https://github.com/LiteyukiStudio/LiteyukiBot/tree/main/liteyuki/
|
||||||
litedoc liteyuki -o docs/en/dev/api -l en -cd class -fd func -md func -vd var -cs -bu https://github.com/LiteyukiStudio/LiteyukiBot/tree/main/liteyuki/
|
litedoc liteyuki -o docs/en/dev/api -l en -cd class -fd func -md func -vd var -bu https://github.com/LiteyukiStudio/LiteyukiBot/tree/main/liteyuki/
|
||||||
|
|
||||||
- name: 安装 pnpm
|
- name: 安装 pnpm
|
||||||
uses: pnpm/action-setup@v2
|
uses: pnpm/action-setup@v2
|
||||||
|
51
.github/workflows/issue_handler.yml
vendored
Normal file
51
.github/workflows/issue_handler.yml
vendored
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
name: Issue Handler
|
||||||
|
|
||||||
|
on:
|
||||||
|
issues:
|
||||||
|
types: [ opened, edited, closed ]
|
||||||
|
|
||||||
|
concurrency:
|
||||||
|
group: issue_handler
|
||||||
|
cancel-in-progress: false
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
check-issue:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout code
|
||||||
|
uses: actions/checkout@v2
|
||||||
|
|
||||||
|
- name: Check issue title
|
||||||
|
id: check_title
|
||||||
|
run: |
|
||||||
|
ISSUE_TITLE="${{ github.event.issue.title }}"
|
||||||
|
if [[ "$ISSUE_TITLE" == Plugin:* || "$ISSUE_TITLE" == Resource:* ]]; then
|
||||||
|
echo "Title starts with Plugin: or Resource:."
|
||||||
|
echo "::set-output name=title_match::true"
|
||||||
|
else
|
||||||
|
echo "Title does not start with Plugin: or Resource:."
|
||||||
|
echo "::set-output name=title_match::false"
|
||||||
|
fi
|
||||||
|
|
||||||
|
- name: Set up Python
|
||||||
|
uses: actions/setup-python@v2
|
||||||
|
if: steps.check_title.outputs.title_match == 'true'
|
||||||
|
with:
|
||||||
|
python-version: '3.12'
|
||||||
|
|
||||||
|
- name: Install dependencies
|
||||||
|
if: steps.check_title.outputs.title_match == 'true'
|
||||||
|
run: |
|
||||||
|
echo "Installing dependencies."
|
||||||
|
pip install -r liteyuki_flow/requirements.txt
|
||||||
|
|
||||||
|
- name: Run Plugin/Resource issue handler
|
||||||
|
if: steps.check_title.outputs.title_match == 'true'
|
||||||
|
run: |
|
||||||
|
echo "Running Plugin/Resource issue handler."
|
||||||
|
python -m liteyuki_flow --handle
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.TOKEN }}
|
||||||
|
ISSUE_NUMBER: ${{ github.event.issue.number }}
|
||||||
|
REPOSITORY: ${{ github.repository }}
|
||||||
|
ACT_TYPE: ${{ github.event.action }}
|
5
.github/workflows/pypi-publish.yml
vendored
5
.github/workflows/pypi-publish.yml
vendored
@@ -1,8 +1,9 @@
|
|||||||
name: Publish
|
name: Publish
|
||||||
|
|
||||||
on:
|
on:
|
||||||
release:
|
push:
|
||||||
types: [published]
|
tags:
|
||||||
|
- 'v*'
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
pypi-publish:
|
pypi-publish:
|
||||||
|
@@ -11,10 +11,9 @@
|
|||||||
[![][Python3.10+]][python-link]
|
[![][Python3.10+]][python-link]
|
||||||
[![][Usage]][usage-link]
|
[![][Usage]][usage-link]
|
||||||
|
|
||||||
- 基于[Nonebot2](https://github.com/nonebot/nonebot2),有良好的生态支持
|
- 原生支持与任意`Python`Bot框架互联,有良好的生态支持
|
||||||
- 开箱即用,无需复杂配置
|
- 开箱即用,无需复杂配置
|
||||||
- 集成包管理器,支持一键安装插件
|
- 集成包管理器,支持一键安装插件
|
||||||
- 支持OneBot标准通信但不限于此
|
|
||||||
- 自定义主题支持,满足审美需求
|
- 自定义主题支持,满足审美需求
|
||||||
- 国际化支持,支持多种语言
|
- 国际化支持,支持多种语言
|
||||||
- 高性能,500插件2s内启动
|
- 高性能,500插件2s内启动
|
||||||
@@ -24,8 +23,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
### 感谢
|
### 感谢
|
||||||
- [NoneBot2](https://nonebot.dev)提供的框架支持
|
- 所有贡献者们
|
||||||
- [nonebot-plugin-alconna](https://github.com/ArcletProject/nonebot-plugin-alconna)提供的命令解析功能
|
|
||||||
|
|
||||||
|
|
||||||
[OneBot]: https://img.shields.io/badge/OneBot-11/12-blue?style=for-the-badge
|
[OneBot]: https://img.shields.io/badge/OneBot-11/12-blue?style=for-the-badge
|
||||||
|
@@ -2,7 +2,6 @@
|
|||||||
|
|
||||||
import {defineConfig} from 'vitepress'
|
import {defineConfig} from 'vitepress'
|
||||||
import {generateSidebar} from 'vitepress-sidebar';
|
import {generateSidebar} from 'vitepress-sidebar';
|
||||||
import VueI18nPlugin from '@intlify/unplugin-vue-i18n/vite'
|
|
||||||
import {zh} from "./zh";
|
import {zh} from "./zh";
|
||||||
import {en} from "./en";
|
import {en} from "./en";
|
||||||
|
|
||||||
@@ -11,7 +10,6 @@ const commonSidebarOptions = {
|
|||||||
collapsed: true,
|
collapsed: true,
|
||||||
convertSameNameSubFileToGroupIndexPage: true,
|
convertSameNameSubFileToGroupIndexPage: true,
|
||||||
useTitleFromFrontmatter: true,
|
useTitleFromFrontmatter: true,
|
||||||
useTitleFromFileHeading: true,
|
|
||||||
useFolderTitleFromIndexFile: true,
|
useFolderTitleFromIndexFile: true,
|
||||||
useFolderLinkFromIndexFile: true,
|
useFolderLinkFromIndexFile: true,
|
||||||
includeFolderIndexFile: true,
|
includeFolderIndexFile: true,
|
||||||
@@ -73,7 +71,13 @@ export const common = defineConfig({
|
|||||||
]
|
]
|
||||||
),
|
),
|
||||||
socialLinks: [
|
socialLinks: [
|
||||||
{icon: 'github', link: 'https://github.com/LiteyukiStudio/LiteyukiBot'}
|
{icon: 'github', link: 'https://github.com/LiteyukiStudio/LiteyukiBot'},
|
||||||
|
{
|
||||||
|
icon: {
|
||||||
|
svg: '<svg t="1725391346807" class="icon" viewBox="0 0 1025 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="5067" width="256" height="256"><path d="M1004.692673 466.396616l-447.094409-447.073929c-25.743103-25.763582-67.501405-25.763582-93.264987 0l-103.873521 103.873521 78.171378 78.171378c12.533635-6.00058 26.562294-9.359266 41.389666-9.359266 53.02219 0 96.00928 42.98709 96.00928 96.00928 0 14.827372-3.358686 28.856031-9.359266 41.389666l127.97824 127.97824c12.533635-6.00058 26.562294-9.359266 41.389666-9.359266 53.02219 0 96.00928 42.98709 96.00928 96.00928s-42.98709 96.00928-96.00928 96.00928-96.00928-42.98709-96.00928-96.00928c0-14.827372 3.358686-28.856031 9.359266-41.389666l-127.97824-127.97824c-3.051489 1.454065-6.184898 2.744293-9.379746 3.870681l0 266.97461c37.273227 13.188988 63.99936 48.721433 63.99936 90.520695 0 53.02219-42.98709 96.00928-96.00928 96.00928s-96.00928-42.98709-96.00928-96.00928c0-41.799262 26.726133-77.331707 63.99936-90.520695l0-266.97461c-37.273227-13.188988-63.99936-48.721433-63.99936-90.520695 0-14.827372 3.358686-28.856031 9.359266-41.389666l-78.171378-78.171378-295.892081 295.871601c-25.743103 25.784062-25.743103 67.542365 0 93.285467l447.114889 447.073929c25.743103 25.743103 67.480925 25.743103 93.264987 0l445.00547-445.00547c25.763582-25.763582 25.763582-67.542365 0-93.285467z" fill="#a2d8f4" p-id="5068"></path></svg>'
|
||||||
|
},
|
||||||
|
link: "https://git.liteyuki.icu/LiteyukiStudio/LiteyukiBot"
|
||||||
|
}
|
||||||
],
|
],
|
||||||
search: {
|
search: {
|
||||||
provider: 'local',
|
provider: 'local',
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
import DefaultTheme from 'vitepress/theme'
|
import DefaultTheme from 'vitepress/theme'
|
||||||
import './liteyuki.css'
|
import './liteyuki.scss'
|
||||||
|
|
||||||
import StatsBar from '../../components/StatsBar.vue'
|
import StatsBar from '../../components/StatsBar.vue'
|
||||||
import PluginStore from '../../components/PluginStore.vue'
|
import PluginStore from '../../components/PluginStore.vue'
|
||||||
|
@@ -1,95 +0,0 @@
|
|||||||
:root {
|
|
||||||
--vp-c-brand-1: #149ef8;
|
|
||||||
--vp-c-brand-2: #0434ad;
|
|
||||||
--vp-home-hero-name-color: transparent;
|
|
||||||
--vp-home-hero-name-background: -webkit-linear-gradient(120deg, #34a3fe 30%, #8d44ff);
|
|
||||||
|
|
||||||
--vp-home-hero-image-background-image: linear-gradient(-45deg, #d0e9ff 50%, #a2d8f4 50%);
|
|
||||||
--vp-home-hero-image-filter: blur(44px);
|
|
||||||
|
|
||||||
--vp-c-gray-1: #eee;
|
|
||||||
--vp-c-gray-2: #aaa;
|
|
||||||
--border-radius-1: 10px;
|
|
||||||
--border-radius-2: 20px;
|
|
||||||
--border-radius-3: 40px;
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
.dark {
|
|
||||||
--vp-home-hero-image-background-image: linear-gradient(-45deg, #004785 50%, #0374ad 50%);
|
|
||||||
--vp-c-gray-1: #333;
|
|
||||||
--vp-c-gray-2: #666;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tab-buttons {
|
|
||||||
padding: 7px;
|
|
||||||
flex: 1;
|
|
||||||
display: flex;
|
|
||||||
justify-content: flex-start;
|
|
||||||
height: 60%;
|
|
||||||
align-items: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
.tab-title {
|
|
||||||
text-align: center;
|
|
||||||
justify-content: center;
|
|
||||||
flex: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
.item-search-box {
|
|
||||||
border-radius: 100px;
|
|
||||||
width: 80%;
|
|
||||||
padding: 10px;
|
|
||||||
margin: 10px 0;
|
|
||||||
border: 1px solid #ccc;
|
|
||||||
}
|
|
||||||
|
|
||||||
.search-box-div {
|
|
||||||
display: flex;
|
|
||||||
justify-content: space-around;
|
|
||||||
margin: 10px 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.item-search-box {
|
|
||||||
width: 80%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.item-card {
|
|
||||||
position: relative;
|
|
||||||
border-radius: 15px;
|
|
||||||
background-color: var(--vp-c-gray-1);
|
|
||||||
height: 160px;
|
|
||||||
padding: 16px;
|
|
||||||
margin: 10px;
|
|
||||||
box-sizing: border-box;
|
|
||||||
transition: background 0.3s ease;
|
|
||||||
}
|
|
||||||
|
|
||||||
.item-name {
|
|
||||||
font-size: 20px;
|
|
||||||
margin-bottom: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.item-description {
|
|
||||||
color: var(--vp-c-gray-2);
|
|
||||||
font-size: 13px;
|
|
||||||
white-space: pre-wrap;
|
|
||||||
}
|
|
||||||
|
|
||||||
.author-info {
|
|
||||||
display: flex;
|
|
||||||
justify-content: left;
|
|
||||||
align-items: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.author-name {
|
|
||||||
font-size: 15px;
|
|
||||||
font-weight: normal;
|
|
||||||
}
|
|
||||||
|
|
||||||
.avatar {
|
|
||||||
border-radius: 50%;
|
|
||||||
margin: 0 10px;
|
|
||||||
}
|
|
149
docs/.vitepress/theme/liteyuki.scss
Normal file
149
docs/.vitepress/theme/liteyuki.scss
Normal file
@@ -0,0 +1,149 @@
|
|||||||
|
:root {
|
||||||
|
--vp-c-brand-1: #149ef8;
|
||||||
|
--vp-c-brand-2: #0434ad;
|
||||||
|
--vp-home-hero-name-color: transparent;
|
||||||
|
--vp-home-hero-name-background: -webkit-linear-gradient(120deg, #34a3fe 30%, #8d44ff);
|
||||||
|
|
||||||
|
--vp-home-hero-image-background-image: linear-gradient(-45deg, #d0e9ff 50%, #a2d8f4 50%);
|
||||||
|
--vp-home-hero-image-filter: blur(44px);
|
||||||
|
|
||||||
|
--vp-c-gray-1: #eee;
|
||||||
|
--vp-c-gray-2: #aaa;
|
||||||
|
--border-radius-1: 10px;
|
||||||
|
--border-radius-2: 20px;
|
||||||
|
--border-radius-3: 40px;
|
||||||
|
--vp-font-family-base: 'Poppins', 'Punctuation SC', 'Inter', ui-sans-serif, system-ui,
|
||||||
|
'PingFang SC', 'Noto Sans CJK SC', 'Noto Sans SC', 'Heiti SC',
|
||||||
|
'Microsoft YaHei', 'DengXian', sans-serif, 'Apple Color Emoji',
|
||||||
|
'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji';
|
||||||
|
--vp-font-family-mono: 'Cousine', monospace;
|
||||||
|
|
||||||
|
--red: #ef4444;
|
||||||
|
--liteyuki-color: #149ef8;
|
||||||
|
--button-radius: 6px;
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
.dark {
|
||||||
|
--vp-home-hero-image-background-image: linear-gradient(-45deg, #004785 50%, #0374ad 50%);
|
||||||
|
--vp-c-gray-1: #333;
|
||||||
|
--vp-c-gray-2: #666;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-buttons {
|
||||||
|
padding: 7px;
|
||||||
|
flex: 1;
|
||||||
|
display: flex;
|
||||||
|
justify-content: flex-start;
|
||||||
|
height: 60%;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.tab-title {
|
||||||
|
text-align: center;
|
||||||
|
justify-content: center;
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.item-search-box {
|
||||||
|
border-radius: 100px;
|
||||||
|
width: 80%;
|
||||||
|
padding: 10px;
|
||||||
|
margin: 10px 0;
|
||||||
|
border: 1px solid #ccc;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-box-div {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-around;
|
||||||
|
margin: 10px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.item-search-box {
|
||||||
|
width: 80%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.item-card {
|
||||||
|
position: relative;
|
||||||
|
border-radius: 15px;
|
||||||
|
background-color: var(--vp-c-gray-1);
|
||||||
|
height: 160px;
|
||||||
|
padding: 16px;
|
||||||
|
margin: 10px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
transition: background 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.item-name {
|
||||||
|
font-size: 20px;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.item-description {
|
||||||
|
color: var(--vp-c-gray-2);
|
||||||
|
font-size: 13px;
|
||||||
|
white-space: pre-wrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.author-info {
|
||||||
|
display: flex;
|
||||||
|
justify-content: left;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.author-name {
|
||||||
|
font-size: 15px;
|
||||||
|
font-weight: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
.avatar {
|
||||||
|
border-radius: 50%;
|
||||||
|
margin: 0 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*store*/
|
||||||
|
|
||||||
|
.store-tabs {
|
||||||
|
display: flex;
|
||||||
|
justify-content: flex-end;
|
||||||
|
margin: 10px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.publish-button {
|
||||||
|
right: 10px;
|
||||||
|
bottom: 10px;
|
||||||
|
padding: 5px 10px;
|
||||||
|
border-radius: 10px;
|
||||||
|
background-color: var(--vp-c-brand-1);
|
||||||
|
color: white;
|
||||||
|
font-size: 15px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pub-window {
|
||||||
|
input {
|
||||||
|
width: 100%;
|
||||||
|
padding: 10px;
|
||||||
|
margin: 10px 0;
|
||||||
|
border-radius: 10px;
|
||||||
|
border: 1px solid #ccc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.pub-option {
|
||||||
|
margin: 10px;
|
||||||
|
padding: 5px;
|
||||||
|
border: 2px solid var(--vp-c-gray-1);
|
||||||
|
border-radius: var(--button-radius);
|
||||||
|
background-color: var(--vp-c-gray-1);
|
||||||
|
|
||||||
|
&.close {
|
||||||
|
}
|
||||||
|
|
||||||
|
&.submit {
|
||||||
|
background-color: var(--vp-c-brand-1);
|
||||||
|
}
|
||||||
|
}
|
26
docs/components/ContributorBar.vue
Normal file
26
docs/components/ContributorBar.vue
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import {getTextRef} from "./scripts/i18n";
|
||||||
|
import {repoPath, repoURL} from "./scripts/const";
|
||||||
|
|
||||||
|
const contributorImgSrc = `https://contrib.rocks/image?repo=${repoPath}`
|
||||||
|
const contributorsUrl = `${repoURL}/graphs/contributors`
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="contributor-bar">
|
||||||
|
<h2>{{ getTextRef('thx_contributors') }}</h2>
|
||||||
|
<a :href="contributorsUrl">
|
||||||
|
<div class="contributor-list">
|
||||||
|
<img :src=contributorImgSrc alt="Contributors">
|
||||||
|
</div>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.contributor-bar {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
</style>
|
@@ -7,7 +7,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="item-bar">
|
<div class="item-bar">
|
||||||
<!-- 三个可点击svg,一个github,一个下载,一个可点击"https://github.com/{{ username }}.png?size=80"个人头像配上id-->
|
<!-- 三个可点击svg,一个github,一个下载,一个可点击"https://github.com/{{ username }}.png?size=80"个人头像配上id-->
|
||||||
<a :href=props.item.homepage class="btn">
|
<a :href=props.item.homepage class="btn" target="_blank">
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 16 16">
|
<svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 16 16">
|
||||||
<path fill="currentColor"
|
<path fill="currentColor"
|
||||||
d="m7.775 3.275l1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0a.751.751 0 0 1 .018-1.042a.751.751 0 0 1 1.042-.018a1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018a.751.751 0 0 1-.018-1.042m-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018a.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0a.751.751 0 0 1-.018 1.042a.751.751 0 0 1-1.042.018a1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83"/>
|
d="m7.775 3.275l1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0a.751.751 0 0 1 .018-1.042a.751.751 0 0 1 1.042-.018a1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018a.751.751 0 0 1-.018-1.042m-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018a.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0a.751.751 0 0 1-.018 1.042a.751.751 0 0 1-1.042.018a1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83"/>
|
||||||
|
@@ -3,6 +3,7 @@ import {computed, ref} from 'vue'
|
|||||||
import ItemCard from './PluginItemCard.vue'
|
import ItemCard from './PluginItemCard.vue'
|
||||||
import ToggleSwitch from "./ToggleSwitch.vue";
|
import ToggleSwitch from "./ToggleSwitch.vue";
|
||||||
import {getTextRef} from "./scripts/i18n";
|
import {getTextRef} from "./scripts/i18n";
|
||||||
|
import pluginsJson from "../public/plugins.json"
|
||||||
|
|
||||||
let showLiteyukiPluginOnly = ref(false)
|
let showLiteyukiPluginOnly = ref(false)
|
||||||
let filteredItems = computed(() => {
|
let filteredItems = computed(() => {
|
||||||
@@ -23,16 +24,11 @@ let filteredItems = computed(() => {
|
|||||||
// 插件商店Nonebot
|
// 插件商店Nonebot
|
||||||
let items = ref([])
|
let items = ref([])
|
||||||
let search = ref('')
|
let search = ref('')
|
||||||
// 从官方拉取
|
// 从轻雪官方拉取,添加轻雪插件属性
|
||||||
fetch("/plugins.json")
|
items.value = pluginsJson
|
||||||
.then(response => response.json())
|
items.value.forEach(item => {
|
||||||
.then(data => {
|
item.is_liteyuki_plugin = true
|
||||||
data.forEach(item => {
|
})
|
||||||
item.is_liteyuki_plugin = true
|
|
||||||
})
|
|
||||||
items.value = data
|
|
||||||
})
|
|
||||||
.catch(error => console.error(error))
|
|
||||||
|
|
||||||
//追加
|
//追加
|
||||||
fetch('https://registry.nonebot.dev/plugins.json')
|
fetch('https://registry.nonebot.dev/plugins.json')
|
||||||
@@ -57,6 +53,11 @@ fetch('https://registry.nonebot.dev/plugins.json')
|
|||||||
<ToggleSwitch v-model:modelValue="showLiteyukiPluginOnly"/>
|
<ToggleSwitch v-model:modelValue="showLiteyukiPluginOnly"/>
|
||||||
{{ getTextRef('liteyukiOnly') }}
|
{{ getTextRef('liteyukiOnly') }}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!-- 按钮们-->
|
||||||
|
<!-- <div class="tab">-->
|
||||||
|
<!-- <button @click="open"-->
|
||||||
|
<!-- </div>-->
|
||||||
<div class="items">
|
<div class="items">
|
||||||
<!-- 使用filteredItems来布局商品 -->
|
<!-- 使用filteredItems来布局商品 -->
|
||||||
<ItemCard v-for="item in filteredItems" :key="item.id" :item="item"/>
|
<ItemCard v-for="item in filteredItems" :key="item.id" :item="item"/>
|
||||||
|
@@ -4,7 +4,7 @@
|
|||||||
<div class="item-description">{{ props.item.description }}</div>
|
<div class="item-description">{{ props.item.description }}</div>
|
||||||
<div class="item-bar">
|
<div class="item-bar">
|
||||||
<!-- 三个可点击svg,一个github,一个下载,一个可点击"https://github.com/{{ username }}.png?size=80"个人头像配上id-->
|
<!-- 三个可点击svg,一个github,一个下载,一个可点击"https://github.com/{{ username }}.png?size=80"个人头像配上id-->
|
||||||
<a :href=props.item.link class="">
|
<a :href=props.item.link class="" target="_blank">
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 16 16">
|
<svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 16 16">
|
||||||
<path fill="currentColor"
|
<path fill="currentColor"
|
||||||
d="m7.775 3.275l1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0a.751.751 0 0 1 .018-1.042a.751.751 0 0 1 1.042-.018a1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018a.751.751 0 0 1-.018-1.042m-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018a.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0a.751.751 0 0 1-.018 1.042a.751.751 0 0 1-1.042.018a1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83"/>
|
d="m7.775 3.275l1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0a.751.751 0 0 1 .018-1.042a.751.751 0 0 1 1.042-.018a1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018a.751.751 0 0 1-.018-1.042m-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018a.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0a.751.751 0 0 1-.018 1.042a.751.751 0 0 1-1.042.018a1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83"/>
|
||||||
|
38
docs/components/ResPubWindow.vue
Normal file
38
docs/components/ResPubWindow.vue
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
<template>
|
||||||
|
<div v-if="isVisible" class="floating-window">
|
||||||
|
<div class="window-content">
|
||||||
|
<slot></slot>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import {defineProps} from 'vue'
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
isVisible: Boolean,
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.floating-window {
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
background: rgba(0, 0, 0, 0.5);
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
z-index: 1000;
|
||||||
|
}
|
||||||
|
|
||||||
|
.window-content {
|
||||||
|
background: var(--vp-c-gray-1);
|
||||||
|
padding: 20px;
|
||||||
|
border-radius: 5px;
|
||||||
|
max-width: 60%;
|
||||||
|
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
|
||||||
|
}
|
||||||
|
</style>
|
@@ -1,8 +1,13 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import {computed, ref} from 'vue'
|
import {computed, ref} from 'vue'
|
||||||
import ItemCard from './ResItemCard.vue'
|
import ItemCard from './ResItemCard.vue'
|
||||||
import * as url from "node:url";
|
import ResPubWindow from "./ResPubWindow.vue";
|
||||||
import {getTextRef} from "./scripts/i18n";
|
import {getTextRef, formatLang} from "./scripts/i18n";
|
||||||
|
import {RepoUrl} from "./scripts/statsApi";
|
||||||
|
|
||||||
|
import resourcesJson from "../public/resources.json"
|
||||||
|
import {useData} from "vitepress";
|
||||||
|
// formLan
|
||||||
|
|
||||||
// 从public/assets/resources.json加载插件
|
// 从public/assets/resources.json加载插件
|
||||||
let filteredItems = computed(() => {
|
let filteredItems = computed(() => {
|
||||||
@@ -18,24 +23,68 @@ let filteredItems = computed(() => {
|
|||||||
// 插件商店Nonebot
|
// 插件商店Nonebot
|
||||||
let items = ref([])
|
let items = ref([])
|
||||||
let search = ref('')
|
let search = ref('')
|
||||||
fetch("/resources.json")
|
items.value = resourcesJson
|
||||||
.then(response => response.json())
|
|
||||||
.then(data => {
|
|
||||||
items.value = data
|
|
||||||
})
|
|
||||||
.catch(error => console.error(error))
|
|
||||||
// 列表倒序
|
// 列表倒序
|
||||||
|
|
||||||
|
const isPublishWindowOpen = ref(false)
|
||||||
|
|
||||||
|
let newRes = ref({
|
||||||
|
name: '',
|
||||||
|
})
|
||||||
|
|
||||||
|
function openPublishWindow() {
|
||||||
|
isPublishWindowOpen.value = true
|
||||||
|
}
|
||||||
|
|
||||||
|
function closePublishWindow() {
|
||||||
|
isPublishWindowOpen.value = false
|
||||||
|
}
|
||||||
|
|
||||||
|
let submitLang = ""
|
||||||
|
if (formatLang(useData().site.value.lang) === "zh") {
|
||||||
|
submitLang = "zh"
|
||||||
|
} else {
|
||||||
|
submitLang = "en"
|
||||||
|
}
|
||||||
|
|
||||||
|
function submitForm() {
|
||||||
|
const title = encodeURI(`Resource: ${newRes.value.name}`)
|
||||||
|
const issueURL = `${RepoUrl}/issues/new?assignees=&labels=Resource&template=resource_publish_${submitLang}.yml&title=${title}`
|
||||||
|
console.log(issueURL)
|
||||||
|
window.open(issueURL, '_blank')
|
||||||
|
}
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="market">
|
<div class="market">
|
||||||
<h1>{{ getTextRef('resourceStore') }}</h1>
|
<h1>{{ getTextRef('resourceStore') }}</h1>
|
||||||
<div class="search-box-div"><input class="item-search-box" type="text" :placeholder="getTextRef('search')" v-model="search" /></div>
|
<div class="search-box-div"><input class="item-search-box" type="text" :placeholder="getTextRef('search')"
|
||||||
|
v-model="search"/></div>
|
||||||
|
<div class="store-tabs" style="display: flex">
|
||||||
|
<button class="store-button publish-button" @click="openPublishWindow">{{ getTextRef('publishRes') }}</button>
|
||||||
|
</div>
|
||||||
<div class="items">
|
<div class="items">
|
||||||
<!-- 使用filteredItems来布局商品 -->
|
<!-- 使用filteredItems来布局商品 -->
|
||||||
<ItemCard v-for="item in filteredItems" :key="item.id" :item="item"/>
|
<ItemCard v-for="item in filteredItems" :key="item.id" :item="item"/>
|
||||||
</div>
|
</div>
|
||||||
|
<ResPubWindow class="pub-window" :is-visible="isPublishWindowOpen">
|
||||||
|
<h2>{{ getTextRef("publishRes") }}</h2>
|
||||||
|
<form @submit.prevent="submitForm">
|
||||||
|
<label for="name">{{ getTextRef("resName") }}</label>
|
||||||
|
<input type="text" id="name" v-model="newRes.name" :placeholder="getTextRef('resNameText')"/>
|
||||||
|
<div class="pub-options" style="display: flex; justify-content: center">
|
||||||
|
<button class="pub-option close" type="button" @click="closePublishWindow">{{
|
||||||
|
getTextRef("closeButtonText")
|
||||||
|
}}
|
||||||
|
</button>
|
||||||
|
<button class="pub-option submit" type="submit" @click="submitForm">{{
|
||||||
|
getTextRef("submitButtonText")
|
||||||
|
}}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</ResPubWindow>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@@ -51,4 +100,6 @@ h1 {
|
|||||||
grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
|
grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
|
||||||
gap: 10px;
|
gap: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
</style>
|
</style>
|
@@ -13,55 +13,55 @@ const dataSections = {
|
|||||||
total: {
|
total: {
|
||||||
name: 'total',
|
name: 'total',
|
||||||
color: '#00a6ff',
|
color: '#00a6ff',
|
||||||
value: ref(2005),
|
value: ref(-1),
|
||||||
link: StarMapUrl
|
link: StarMapUrl
|
||||||
},
|
},
|
||||||
online: {
|
online: {
|
||||||
name: 'online',
|
name: 'online',
|
||||||
color: '#7eff7e',
|
color: '#7eff7e',
|
||||||
value: ref(1145),
|
value: ref(-1),
|
||||||
link: StarMapUrl
|
link: StarMapUrl
|
||||||
},
|
},
|
||||||
stars: {
|
stars: {
|
||||||
name: 'stars',
|
name: 'stars',
|
||||||
color: '#ffcc00',
|
color: '#ffcc00',
|
||||||
value: ref(1234),
|
value: ref(-1),
|
||||||
link: `${RepoUrl}/stargazers`
|
link: `${RepoUrl}/stargazers`
|
||||||
},
|
},
|
||||||
forks: {
|
forks: {
|
||||||
name: 'forks',
|
name: 'forks',
|
||||||
color: '#ff6600',
|
color: '#ff6600',
|
||||||
value: ref(9420),
|
value: ref(-1),
|
||||||
link: `${RepoUrl}/forks`
|
link: `${RepoUrl}/forks`
|
||||||
},
|
},
|
||||||
issues: {
|
issues: {
|
||||||
name: 'issues',
|
name: 'issues',
|
||||||
color: '#ff0000',
|
color: '#ff0000',
|
||||||
value: ref(1145),
|
value: ref(-1),
|
||||||
link: `${RepoUrl}/issues`
|
link: `${RepoUrl}/issues`
|
||||||
},
|
},
|
||||||
prs: {
|
prs: {
|
||||||
name: 'prs',
|
name: 'prs',
|
||||||
color: '#f15df1',
|
color: '#f15df1',
|
||||||
value: ref(6543),
|
value: ref(-1),
|
||||||
link: `${RepoUrl}/pulls`
|
link: `${RepoUrl}/pulls`
|
||||||
},
|
},
|
||||||
plugins: {
|
plugins: {
|
||||||
name: 'plugins',
|
name: 'plugins',
|
||||||
color: '#a766ff',
|
color: '#a766ff',
|
||||||
value: ref(1763),
|
value: ref(-1),
|
||||||
link: './store/plugin'
|
link: './store/plugin'
|
||||||
},
|
},
|
||||||
resources: {
|
resources: {
|
||||||
name: 'resources',
|
name: 'resources',
|
||||||
color: '#5a54fa',
|
color: '#5a54fa',
|
||||||
value: ref(6789),
|
value: ref(-1),
|
||||||
link: './store/resource'
|
link: './store/resource'
|
||||||
},
|
},
|
||||||
visitors: {
|
visitors: {
|
||||||
name: 'visitors',
|
name: 'visitors',
|
||||||
color: '#00a6ff',
|
color: '#00a6ff',
|
||||||
value: ref(1234),
|
value: ref(-1),
|
||||||
link: RepoUrl
|
link: RepoUrl
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@@ -109,7 +109,20 @@ onBeforeRouteUpdate(() => {
|
|||||||
updateRefData();
|
updateRefData();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
console.log(
|
||||||
|
" _ _ _ _ _ ____ _ \n" +
|
||||||
|
" | | (_) | | | (_) _ \\ | | \n" +
|
||||||
|
" | | _| |_ ___ _ _ _ _| | ___| |_) | ___ | |_ \n" +
|
||||||
|
" | | | | __/ _ \\ | | | | | | |/ / | _ < / _ \\| __|\n" +
|
||||||
|
" | |____| | || __/ |_| | |_| | <| | |_) | (_) | |_ \n" +
|
||||||
|
" |______|_|\\__\\___|\\__, |\\__,_|_|\\_\\_|____/ \\___/ \\__|\n" +
|
||||||
|
" __/ | \n" +
|
||||||
|
" |___/ "
|
||||||
|
)
|
||||||
|
|
||||||
|
console.log(
|
||||||
|
getTextRef('easterEgg')
|
||||||
|
)
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@@ -133,7 +146,8 @@ onBeforeRouteUpdate(() => {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="starmap">
|
<div class="starmap">
|
||||||
<iframe src="https://starmap.liteyuki.icu/" width="100%" height="300px" class="gamma"></iframe>
|
<iframe src="https://starmap.liteyuki.icu/" width="100%" height="300px" class="gamma">
|
||||||
|
</iframe>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -267,7 +281,7 @@ onBeforeRouteUpdate(() => {
|
|||||||
|
|
||||||
.stats-info {
|
.stats-info {
|
||||||
width: 40%;
|
width: 40%;
|
||||||
margin: 30px;
|
margin: 10px 30px 30px 30px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.starmap {
|
.starmap {
|
||||||
|
11
docs/components/TryLiteyukiWindow.vue
Normal file
11
docs/components/TryLiteyukiWindow.vue
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
|
||||||
|
</style>
|
4
docs/components/scripts/const.ts
Normal file
4
docs/components/scripts/const.ts
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
export const platformBaseURL = "https://github.com/"
|
||||||
|
export const repoPath = "LiteyukiStudio/LiteyukiBot"
|
||||||
|
|
||||||
|
export const repoURL = `${platformBaseURL}${repoPath}`
|
@@ -13,7 +13,7 @@ const i18nData = {
|
|||||||
forks: 'Forks',
|
forks: 'Forks',
|
||||||
issues: 'Issues',
|
issues: 'Issues',
|
||||||
prs: 'Pull Requests',
|
prs: 'Pull Requests',
|
||||||
visitors: 'Visitor',
|
visitors: 'Visitors',
|
||||||
size: 'Size',
|
size: 'Size',
|
||||||
plugins: 'Plugins',
|
plugins: 'Plugins',
|
||||||
resources: 'Resources',
|
resources: 'Resources',
|
||||||
@@ -22,6 +22,25 @@ const i18nData = {
|
|||||||
liteyukiOnly: 'Liteyuki Only',
|
liteyukiOnly: 'Liteyuki Only',
|
||||||
search: 'Search',
|
search: 'Search',
|
||||||
resourceStore: 'Resources Store',
|
resourceStore: 'Resources Store',
|
||||||
|
thx_contributors: 'Thanks the following contributors!',
|
||||||
|
easterEgg: 'Congratulations on finding the Easter egg!',
|
||||||
|
|
||||||
|
publishPlugin: 'Publish Plugin',
|
||||||
|
publishRes: 'Publish Resource',
|
||||||
|
closeButtonText: 'Close',
|
||||||
|
submitButtonText: 'Submit',
|
||||||
|
|
||||||
|
resName: 'Name',
|
||||||
|
resDesc: 'Description',
|
||||||
|
resAuthor: 'Author',
|
||||||
|
resLink: 'Download Link',
|
||||||
|
resHomepage: 'Homepage',
|
||||||
|
|
||||||
|
resNameText: 'Example: Kawaii Style Theme',
|
||||||
|
resDescText: 'Example: A kawaii style and color theme',
|
||||||
|
resAuthorText: 'Usually the github username, Example: yanyongyu',
|
||||||
|
resLinkText: 'Direct download link, usually zip package link',
|
||||||
|
resHomepageText: 'Optional, can be the name of the git platform repository"',
|
||||||
},
|
},
|
||||||
zh: {
|
zh: {
|
||||||
stats: '统计信息',
|
stats: '统计信息',
|
||||||
@@ -30,9 +49,9 @@ const i18nData = {
|
|||||||
total: '实例',
|
total: '实例',
|
||||||
fetching: '获取中',
|
fetching: '获取中',
|
||||||
stars: '星星',
|
stars: '星星',
|
||||||
forks: '叉子',
|
forks: '分叉',
|
||||||
issues: '开启议题',
|
issues: '议题',
|
||||||
prs: '合并请求',
|
prs: '拉取请求',
|
||||||
visitors: '访客',
|
visitors: '访客',
|
||||||
size: '大小',
|
size: '大小',
|
||||||
plugins: '插件',
|
plugins: '插件',
|
||||||
@@ -43,6 +62,25 @@ const i18nData = {
|
|||||||
liteyukiOnly: '仅轻雪',
|
liteyukiOnly: '仅轻雪',
|
||||||
search: '搜索',
|
search: '搜索',
|
||||||
resourceStore: '资源商店',
|
resourceStore: '资源商店',
|
||||||
|
thx_contributors: '感谢以下贡献者!',
|
||||||
|
easterEgg: '恭喜你发现了彩蛋!',
|
||||||
|
|
||||||
|
publishPlugin: '发布插件',
|
||||||
|
publishRes: '发布资源',
|
||||||
|
closeButtonText: '关闭',
|
||||||
|
submitButtonText: '提交',
|
||||||
|
|
||||||
|
resName: '名称',
|
||||||
|
resDesc: '描述',
|
||||||
|
resAuthor: '作者',
|
||||||
|
resLink: '下载链接',
|
||||||
|
resHomepage: '主页',
|
||||||
|
|
||||||
|
resNameText: '示例:可爱风格主题',
|
||||||
|
resDescText: '示例:一个可爱风格和配色的主题',
|
||||||
|
resAuthorText: '通常为github用户名,示例:yanyongyu',
|
||||||
|
resLinkText: '直接下载链接,通常为zip包链接',
|
||||||
|
resHomepageText: '可选,可为git平台仓库名',
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -53,7 +91,7 @@ function getText(lang: string, key: string): string {
|
|||||||
return i18nData[lang][key];
|
return i18nData[lang][key];
|
||||||
}
|
}
|
||||||
|
|
||||||
function formatLang(lang: string): string {
|
export function formatLang(lang: string): string {
|
||||||
if (lang.includes('-')) {
|
if (lang.includes('-')) {
|
||||||
return lang.split('-')[0];
|
return lang.split('-')[0];
|
||||||
}
|
}
|
||||||
@@ -70,5 +108,5 @@ export function updateRefData() {
|
|||||||
export function getTextRef(key: string): any {
|
export function getTextRef(key: string): any {
|
||||||
const lang = formatLang(useData().site.value.lang);
|
const lang = formatLang(useData().site.value.lang);
|
||||||
refData[key] = getText(lang, key);
|
refData[key] = getText(lang, key);
|
||||||
return refData[key]
|
return refData[key] || key;
|
||||||
}
|
}
|
@@ -2,6 +2,7 @@
|
|||||||
export const OWNER = "LiteyukiStudio"
|
export const OWNER = "LiteyukiStudio"
|
||||||
export const REPO = "LiteyukiBot"
|
export const REPO = "LiteyukiBot"
|
||||||
const githubAPIUrl = "https://api.github.com"
|
const githubAPIUrl = "https://api.github.com"
|
||||||
|
const giteaAPIUrl = "https://git.liteyuki.icu/api/v1"
|
||||||
const onlineFetchUrl = "https://api.liteyuki.icu/online";
|
const onlineFetchUrl = "https://api.liteyuki.icu/online";
|
||||||
const totalFetchUrl = "https://api.liteyuki.icu/count";
|
const totalFetchUrl = "https://api.liteyuki.icu/count";
|
||||||
const visitRecordUrl = "https://api.liteyuki.icu/visit";
|
const visitRecordUrl = "https://api.liteyuki.icu/visit";
|
||||||
@@ -32,28 +33,34 @@ interface StatsApi {
|
|||||||
|
|
||||||
export type {GithubStats};
|
export type {GithubStats};
|
||||||
|
|
||||||
// 实现接口
|
async function getGiteaStats() {
|
||||||
export const statsApi: StatsApi = {
|
try {
|
||||||
getTotal: async () => {
|
const url = `${giteaAPIUrl}/repos/${OWNER}/${REPO}`;
|
||||||
try {
|
console.log(url);
|
||||||
const res = await fetch(totalFetchUrl);
|
const res = await fetch(url);
|
||||||
const data = await res.json();
|
const data = await res.json();
|
||||||
return data.register;
|
return {
|
||||||
} catch (e) {
|
stars: data.stars_count,
|
||||||
return -1;
|
forks: data.forks_count,
|
||||||
}
|
watchers: data.watchers_count,
|
||||||
},
|
issues: 0,
|
||||||
getOnline: async () => {
|
prs: 0,
|
||||||
try {
|
size: data.size,
|
||||||
const res = await fetch(onlineFetchUrl);
|
};
|
||||||
const data = await res.json();
|
} catch (e) {
|
||||||
return data.online;
|
return {
|
||||||
} catch (e) {
|
stars: -1,
|
||||||
return -1;
|
forks: -1,
|
||||||
}
|
watchers: -1,
|
||||||
},
|
issues: -1,
|
||||||
getGithubStats: async () => {
|
prs: -1,
|
||||||
try {
|
size: -1,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function getGithubStats() {
|
||||||
|
try {
|
||||||
const res = await fetch(`${githubAPIUrl}/repos/${OWNER}/${REPO}`);
|
const res = await fetch(`${githubAPIUrl}/repos/${OWNER}/${REPO}`);
|
||||||
const data = await res.json();
|
const data = await res.json();
|
||||||
return {
|
return {
|
||||||
@@ -74,7 +81,43 @@ export const statsApi: StatsApi = {
|
|||||||
size: -1,
|
size: -1,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function getRepoStats() {
|
||||||
|
// 两个接口各数据,加和返回
|
||||||
|
const githubStats = await getGithubStats();
|
||||||
|
const giteaStats = await getGiteaStats();
|
||||||
|
return {
|
||||||
|
stars: githubStats.stars + giteaStats.stars,
|
||||||
|
forks: githubStats.forks + giteaStats.forks,
|
||||||
|
watchers: githubStats.watchers + giteaStats.watchers,
|
||||||
|
issues: githubStats.issues + giteaStats.issues,
|
||||||
|
prs: githubStats.prs + giteaStats.prs,
|
||||||
|
size: githubStats.size + giteaStats.size,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// 实现接口
|
||||||
|
export const statsApi: StatsApi = {
|
||||||
|
getTotal: async () => {
|
||||||
|
try {
|
||||||
|
const res = await fetch(totalFetchUrl);
|
||||||
|
const data = await res.json();
|
||||||
|
return data.register;
|
||||||
|
} catch (e) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
getOnline: async () => {
|
||||||
|
try {
|
||||||
|
const res = await fetch(onlineFetchUrl);
|
||||||
|
const data = await res.json();
|
||||||
|
return data.online;
|
||||||
|
} catch (e) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
getGithubStats: getRepoStats,
|
||||||
getPluginNum: async () => {
|
getPluginNum: async () => {
|
||||||
try {
|
try {
|
||||||
const res = await fetch('/plugins.json');
|
const res = await fetch('/plugins.json');
|
||||||
|
21
docs/en/dev/best_practices.md
Normal file
21
docs/en/dev/best_practices.md
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
---
|
||||||
|
title: Best Practices
|
||||||
|
order: 10
|
||||||
|
---
|
||||||
|
|
||||||
|
# Best Practices
|
||||||
|
|
||||||
|
## Bot applications
|
||||||
|
- [LiteyukiBot](https://github.com/LiteyukiStudio/LiteyukiBot): Liteyuki Official Bot
|
||||||
|
- [LiteyukiBot-TriM](https://github.com/TriM-Organization/LiteyukiBot-TriM): TriM Official Custom Liteyuki Bot
|
||||||
|
- [Liteyuki Marsho](https://git.liteyuki.icu/LiteyukiStudio/marsho-alpha): A cute cat girl bot based on Liteyuki and the github model
|
||||||
|
|
||||||
|
## plugins
|
||||||
|
- [liteyukibot-plugin-nonebot](https://github.com/LiteyukiStudio/liteyukibot-plugin-nonebot): Liteyuki Bot NoneBot plugin, allowing Liteyuki to support NoneBot
|
||||||
|
- [nonebot-plugin-liteyukibot](https://github.com/LiteyukiStudio/nonebot-plugin-liteyukibot): NoneBot plugin, allowing NoneBot to support Liteyuki
|
||||||
|
|
||||||
|
## Others
|
||||||
|
- [liteyuki starmap](https://starmap.liteyuki.icu): Liteyuki official star map, showing all instances of Liteyuki and their location distribution
|
||||||
|
- [TRSS_Liteyuki](https://timerainstarsky.github.io/TRSS_Liteyuki/): LiteyukiBot management script
|
||||||
|
- [litedoc](https://github.com/LiteyukiStudio/litedoc): Liteyuki API documentation generator
|
||||||
|
- liteyukibot-api (closed source): Liteyuki Bot stat interface
|
@@ -1,5 +1,5 @@
|
|||||||
---
|
---
|
||||||
title: 进程通信
|
title: Process Communication
|
||||||
order: 4
|
order: 4
|
||||||
---
|
---
|
||||||
|
|
||||||
|
@@ -2,6 +2,12 @@
|
|||||||
title: Development Guide
|
title: Development Guide
|
||||||
order: 0
|
order: 0
|
||||||
---
|
---
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import ContributorBar from '../../components/ContributorBar.vue'
|
||||||
|
</script>
|
||||||
|
|
||||||
|
|
||||||
# Development Guide
|
# Development Guide
|
||||||
|
|
||||||
## How to Develop
|
## How to Develop
|
||||||
@@ -52,8 +58,8 @@ The `src` directory is the application part, please develop business logic in th
|
|||||||
- commit message should follow the following guidelines:
|
- commit message should follow the following guidelines:
|
||||||
- You should commit the code after completing a feature or fixing a bug, and not mix the code of multiple features or bugs together.
|
- You should commit the code after completing a feature or fixing a bug, and not mix the code of multiple features or bugs together.
|
||||||
- We use gitmoji to mark the type of commit, such as `:sparkles:` for introducing new features, `:bug:` for fixing bugs, etc., please refer to [gitmoji](https://gitmoji.dev/) for details.
|
- We use gitmoji to mark the type of commit, such as `:sparkles:` for introducing new features, `:bug:` for fixing bugs, etc., please refer to [gitmoji](https://gitmoji.dev/) for details.
|
||||||
- The format of the commit message is `<emoji> [module]: <message>`, such as `:sparkles: [liteyuki.event]: add new feature`,
|
- The format of the commit message is `<emoji> [type:] <message>`, such as `:sparkles: feat: add new field to event`,
|
||||||
where the module field is the affected part, such as `liteyuki.message`, `docs.en.guide.md`, etc., not much is required, but please fill in as much as possible; the message field is a brief description, in summary, what you did.
|
where the type field is the type of commit, not much is required, but please fill in as much as possible; the message field is a brief description, in summary, what you did.
|
||||||
- There is no restriction on the language of the commit message, and bilingual use is possible if conditions permit.
|
- There is no restriction on the language of the commit message, and bilingual use is possible if conditions permit.
|
||||||
- The documentation should follow [`Markdown`](https://www.markdownguide.org/) syntax and support vitepress-related content:
|
- The documentation should follow [`Markdown`](https://www.markdownguide.org/) syntax and support vitepress-related content:
|
||||||
- Revise the documentation for each language when editing.
|
- Revise the documentation for each language when editing.
|
||||||
@@ -62,3 +68,6 @@ The `src` directory is the application part, please develop business logic in th
|
|||||||
|
|
||||||
## Finally
|
## Finally
|
||||||
- This project is a non-profit open-source project, and we welcome anyone to participate in development. Your contributions will make Liteyuki better.
|
- This project is a non-profit open-source project, and we welcome anyone to participate in development. Your contributions will make Liteyuki better.
|
||||||
|
|
||||||
|
|
||||||
|
<ContributorBar />
|
@@ -1,5 +1,5 @@
|
|||||||
---
|
---
|
||||||
title: 轻雪函数
|
title: Liteyuki Function
|
||||||
order: 2
|
order: 2
|
||||||
---
|
---
|
||||||
|
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
---
|
---
|
||||||
title: 轻雪插件开发
|
title: Liteyuki Plugin
|
||||||
order: 3
|
order: 3
|
||||||
---
|
---
|
||||||
|
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
---
|
---
|
||||||
title: 资源包开发
|
title: Resource Pack
|
||||||
order: 1
|
order: 1
|
||||||
---
|
---
|
||||||
|
|
||||||
|
@@ -14,16 +14,19 @@ hero:
|
|||||||
- theme: alt
|
- theme: alt
|
||||||
text: 📦 Extensions
|
text: 📦 Extensions
|
||||||
link: ./store/
|
link: ./store/
|
||||||
|
- theme: alt
|
||||||
|
text: 🛠️ Development
|
||||||
|
link: ./dev/guide
|
||||||
image:
|
image:
|
||||||
light: ./liteyuki.svg
|
light: /liteyuki.svg
|
||||||
dark: ./liteyuki-dark.svg
|
dark: /liteyuki-dark.svg
|
||||||
alt: Liteyuki Logo
|
alt: Liteyuki Logo
|
||||||
|
|
||||||
features:
|
features:
|
||||||
- title: Ecological Diversity
|
- title: Ecological Diversity
|
||||||
icon: 🛠️
|
icon: 🛠️
|
||||||
details: Based on the liteyuki framework, compatible with any Python bot framework and application
|
details: Based on the liteyuki framework, compatible with any Python bot framework and application
|
||||||
link: ./dev/api/api
|
link: ./dev/api
|
||||||
|
|
||||||
- title: Pluggable
|
- title: Pluggable
|
||||||
icon: 🧩
|
icon: 🧩
|
||||||
|
@@ -1,8 +1,9 @@
|
|||||||
{
|
{
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@intlify/unplugin-vue-i18n": "^4.0.0",
|
"@intlify/unplugin-vue-i18n": "^4.0.0",
|
||||||
|
"sass-embedded": "^1.78.0",
|
||||||
"vitepress": "^1.3.4",
|
"vitepress": "^1.3.4",
|
||||||
"vitepress-sidebar": "^1.25.0"
|
"vitepress-sidebar": "^1.25.3"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"docs:dev": "vitepress dev --host",
|
"docs:dev": "vitepress dev --host",
|
||||||
|
340
docs/pnpm-lock.yaml
generated
340
docs/pnpm-lock.yaml
generated
@@ -22,56 +22,59 @@ devDependencies:
|
|||||||
'@intlify/unplugin-vue-i18n':
|
'@intlify/unplugin-vue-i18n':
|
||||||
specifier: ^4.0.0
|
specifier: ^4.0.0
|
||||||
version: 4.0.0
|
version: 4.0.0
|
||||||
|
sass-embedded:
|
||||||
|
specifier: ^1.78.0
|
||||||
|
version: 1.78.0
|
||||||
vitepress:
|
vitepress:
|
||||||
specifier: ^1.3.4
|
specifier: ^1.3.4
|
||||||
version: 1.3.4(@algolia/client-search@5.2.3)(search-insights@2.17.0)
|
version: 1.3.4(@algolia/client-search@5.2.4)(sass-embedded@1.78.0)(search-insights@2.17.1)
|
||||||
vitepress-sidebar:
|
vitepress-sidebar:
|
||||||
specifier: ^1.25.0
|
specifier: ^1.25.3
|
||||||
version: 1.25.0
|
version: 1.25.3
|
||||||
|
|
||||||
packages:
|
packages:
|
||||||
|
|
||||||
/@algolia/autocomplete-core@1.9.3(@algolia/client-search@5.2.3)(algoliasearch@4.24.0)(search-insights@2.17.0):
|
/@algolia/autocomplete-core@1.9.3(@algolia/client-search@5.2.4)(algoliasearch@4.24.0)(search-insights@2.17.1):
|
||||||
resolution: {integrity: sha512-009HdfugtGCdC4JdXUbVJClA0q0zh24yyePn+KUGk3rP7j8FEe/m5Yo/z65gn6nP/cM39PxpzqKrL7A6fP6PPw==}
|
resolution: {integrity: sha512-009HdfugtGCdC4JdXUbVJClA0q0zh24yyePn+KUGk3rP7j8FEe/m5Yo/z65gn6nP/cM39PxpzqKrL7A6fP6PPw==}
|
||||||
dependencies:
|
dependencies:
|
||||||
'@algolia/autocomplete-plugin-algolia-insights': 1.9.3(@algolia/client-search@5.2.3)(algoliasearch@4.24.0)(search-insights@2.17.0)
|
'@algolia/autocomplete-plugin-algolia-insights': 1.9.3(@algolia/client-search@5.2.4)(algoliasearch@4.24.0)(search-insights@2.17.1)
|
||||||
'@algolia/autocomplete-shared': 1.9.3(@algolia/client-search@5.2.3)(algoliasearch@4.24.0)
|
'@algolia/autocomplete-shared': 1.9.3(@algolia/client-search@5.2.4)(algoliasearch@4.24.0)
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- '@algolia/client-search'
|
- '@algolia/client-search'
|
||||||
- algoliasearch
|
- algoliasearch
|
||||||
- search-insights
|
- search-insights
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/@algolia/autocomplete-plugin-algolia-insights@1.9.3(@algolia/client-search@5.2.3)(algoliasearch@4.24.0)(search-insights@2.17.0):
|
/@algolia/autocomplete-plugin-algolia-insights@1.9.3(@algolia/client-search@5.2.4)(algoliasearch@4.24.0)(search-insights@2.17.1):
|
||||||
resolution: {integrity: sha512-a/yTUkcO/Vyy+JffmAnTWbr4/90cLzw+CC3bRbhnULr/EM0fGNvM13oQQ14f2moLMcVDyAx/leczLlAOovhSZg==}
|
resolution: {integrity: sha512-a/yTUkcO/Vyy+JffmAnTWbr4/90cLzw+CC3bRbhnULr/EM0fGNvM13oQQ14f2moLMcVDyAx/leczLlAOovhSZg==}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
search-insights: '>= 1 < 3'
|
search-insights: '>= 1 < 3'
|
||||||
dependencies:
|
dependencies:
|
||||||
'@algolia/autocomplete-shared': 1.9.3(@algolia/client-search@5.2.3)(algoliasearch@4.24.0)
|
'@algolia/autocomplete-shared': 1.9.3(@algolia/client-search@5.2.4)(algoliasearch@4.24.0)
|
||||||
search-insights: 2.17.0
|
search-insights: 2.17.1
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- '@algolia/client-search'
|
- '@algolia/client-search'
|
||||||
- algoliasearch
|
- algoliasearch
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/@algolia/autocomplete-preset-algolia@1.9.3(@algolia/client-search@5.2.3)(algoliasearch@4.24.0):
|
/@algolia/autocomplete-preset-algolia@1.9.3(@algolia/client-search@5.2.4)(algoliasearch@4.24.0):
|
||||||
resolution: {integrity: sha512-d4qlt6YmrLMYy95n5TB52wtNDr6EgAIPH81dvvvW8UmuWRgxEtY0NJiPwl/h95JtG2vmRM804M0DSwMCNZlzRA==}
|
resolution: {integrity: sha512-d4qlt6YmrLMYy95n5TB52wtNDr6EgAIPH81dvvvW8UmuWRgxEtY0NJiPwl/h95JtG2vmRM804M0DSwMCNZlzRA==}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
'@algolia/client-search': '>= 4.9.1 < 6'
|
'@algolia/client-search': '>= 4.9.1 < 6'
|
||||||
algoliasearch: '>= 4.9.1 < 6'
|
algoliasearch: '>= 4.9.1 < 6'
|
||||||
dependencies:
|
dependencies:
|
||||||
'@algolia/autocomplete-shared': 1.9.3(@algolia/client-search@5.2.3)(algoliasearch@4.24.0)
|
'@algolia/autocomplete-shared': 1.9.3(@algolia/client-search@5.2.4)(algoliasearch@4.24.0)
|
||||||
'@algolia/client-search': 5.2.3
|
'@algolia/client-search': 5.2.4
|
||||||
algoliasearch: 4.24.0
|
algoliasearch: 4.24.0
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/@algolia/autocomplete-shared@1.9.3(@algolia/client-search@5.2.3)(algoliasearch@4.24.0):
|
/@algolia/autocomplete-shared@1.9.3(@algolia/client-search@5.2.4)(algoliasearch@4.24.0):
|
||||||
resolution: {integrity: sha512-Wnm9E4Ye6Rl6sTTqjoymD+l8DjSTHsHboVRYrKgEt8Q7UHm9nYbqhN/i0fhUYA3OAEH7WA8x3jfpnmJm3rKvaQ==}
|
resolution: {integrity: sha512-Wnm9E4Ye6Rl6sTTqjoymD+l8DjSTHsHboVRYrKgEt8Q7UHm9nYbqhN/i0fhUYA3OAEH7WA8x3jfpnmJm3rKvaQ==}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
'@algolia/client-search': '>= 4.9.1 < 6'
|
'@algolia/client-search': '>= 4.9.1 < 6'
|
||||||
algoliasearch: '>= 4.9.1 < 6'
|
algoliasearch: '>= 4.9.1 < 6'
|
||||||
dependencies:
|
dependencies:
|
||||||
'@algolia/client-search': 5.2.3
|
'@algolia/client-search': 5.2.4
|
||||||
algoliasearch: 4.24.0
|
algoliasearch: 4.24.0
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
@@ -115,8 +118,8 @@ packages:
|
|||||||
'@algolia/transporter': 4.24.0
|
'@algolia/transporter': 4.24.0
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/@algolia/client-common@5.2.3:
|
/@algolia/client-common@5.2.4:
|
||||||
resolution: {integrity: sha512-zqfcbgjYR72Y/rx/+/6g5Li/eV33yhRq5mkGbU06JYBzvGq6viy0gZl1ckCFhLLifKzXZ4yzUQTw/KG6FV+smg==}
|
resolution: {integrity: sha512-xNkNJ9Vk1WjxEU/SzcA2vZWeYSiQFQOUS7Akffx8aeAIJIOcmwbpLr2D8JzBEC4QNmNb5KAZOJTrGl1ri9Mclg==}
|
||||||
engines: {node: '>= 14.0.0'}
|
engines: {node: '>= 14.0.0'}
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
@@ -136,13 +139,13 @@ packages:
|
|||||||
'@algolia/transporter': 4.24.0
|
'@algolia/transporter': 4.24.0
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/@algolia/client-search@5.2.3:
|
/@algolia/client-search@5.2.4:
|
||||||
resolution: {integrity: sha512-xXdCg8vpiwE8gqSyvjxq8V3qbFa+gHasY5epIz718IByWv3WKLLi/n4SMIfB/zRwXTLVWeGOH/UJSz5VCnAAqg==}
|
resolution: {integrity: sha512-xlBaro8nU5EvsNsLu8dSsd7jzHVvOVGCOTW4dM6gjRmQDYChzMsF69Tb1OfLaXk7YJ0jHk1rNeccBOsYBtQcIQ==}
|
||||||
engines: {node: '>= 14.0.0'}
|
engines: {node: '>= 14.0.0'}
|
||||||
dependencies:
|
dependencies:
|
||||||
'@algolia/client-common': 5.2.3
|
'@algolia/client-common': 5.2.4
|
||||||
'@algolia/requester-browser-xhr': 5.2.3
|
'@algolia/requester-browser-xhr': 5.2.4
|
||||||
'@algolia/requester-node-http': 5.2.3
|
'@algolia/requester-node-http': 5.2.4
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/@algolia/logger-common@4.24.0:
|
/@algolia/logger-common@4.24.0:
|
||||||
@@ -177,11 +180,11 @@ packages:
|
|||||||
'@algolia/requester-common': 4.24.0
|
'@algolia/requester-common': 4.24.0
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/@algolia/requester-browser-xhr@5.2.3:
|
/@algolia/requester-browser-xhr@5.2.4:
|
||||||
resolution: {integrity: sha512-lezcE4E7ax7JkDGDKA/xAnyAY9p9LZ4AxzsyL0pksqUpOvn4U0msP553M2yJRfsxxdGDp15noCnPuRsh7u8dMg==}
|
resolution: {integrity: sha512-ncssmlq86ZnoQ/RH/EEG2KgmBZQnprzx3dZZ+iJrvkbxIi8V9wBWyCgjsuPrKGitzhpnjxZLNlHJZtcps5jaXw==}
|
||||||
engines: {node: '>= 14.0.0'}
|
engines: {node: '>= 14.0.0'}
|
||||||
dependencies:
|
dependencies:
|
||||||
'@algolia/client-common': 5.2.3
|
'@algolia/client-common': 5.2.4
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/@algolia/requester-common@4.24.0:
|
/@algolia/requester-common@4.24.0:
|
||||||
@@ -194,11 +197,11 @@ packages:
|
|||||||
'@algolia/requester-common': 4.24.0
|
'@algolia/requester-common': 4.24.0
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/@algolia/requester-node-http@5.2.3:
|
/@algolia/requester-node-http@5.2.4:
|
||||||
resolution: {integrity: sha512-xTxsRnJqxG1dylIkxmflrHO9LJfJKjSHqEF5yGdRrtnqIEvb2hiQPCHm2XwqxMa3NBcf6lmydGfJqhPLnRJwtw==}
|
resolution: {integrity: sha512-EoLOebO81Dtwuz/hy4onmQAb9dK8fDqyPWMwX017SvGDi3w1h4i6W6//VTO0vKLfXMNpoAKWFi+LBBTLCVtiiw==}
|
||||||
engines: {node: '>= 14.0.0'}
|
engines: {node: '>= 14.0.0'}
|
||||||
dependencies:
|
dependencies:
|
||||||
'@algolia/client-common': 5.2.3
|
'@algolia/client-common': 5.2.4
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/@algolia/transporter@4.24.0:
|
/@algolia/transporter@4.24.0:
|
||||||
@@ -232,14 +235,18 @@ packages:
|
|||||||
'@babel/helper-validator-identifier': 7.24.7
|
'@babel/helper-validator-identifier': 7.24.7
|
||||||
to-fast-properties: 2.0.0
|
to-fast-properties: 2.0.0
|
||||||
|
|
||||||
|
/@bufbuild/protobuf@1.10.0:
|
||||||
|
resolution: {integrity: sha512-QDdVFLoN93Zjg36NoQPZfsVH9tZew7wKDKyV5qRdj8ntT4wQCOradQjRaTdwMhWUYsgKsvCINKKm87FdEk96Ag==}
|
||||||
|
dev: true
|
||||||
|
|
||||||
/@docsearch/css@3.6.1:
|
/@docsearch/css@3.6.1:
|
||||||
resolution: {integrity: sha512-VtVb5DS+0hRIprU2CO6ZQjK2Zg4QU5HrDM1+ix6rT0umsYvFvatMAnf97NHZlVWDaaLlx7GRfR/7FikANiM2Fg==}
|
resolution: {integrity: sha512-VtVb5DS+0hRIprU2CO6ZQjK2Zg4QU5HrDM1+ix6rT0umsYvFvatMAnf97NHZlVWDaaLlx7GRfR/7FikANiM2Fg==}
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/@docsearch/js@3.6.1(@algolia/client-search@5.2.3)(search-insights@2.17.0):
|
/@docsearch/js@3.6.1(@algolia/client-search@5.2.4)(search-insights@2.17.1):
|
||||||
resolution: {integrity: sha512-erI3RRZurDr1xES5hvYJ3Imp7jtrXj6f1xYIzDzxiS7nNBufYWPbJwrmMqWC5g9y165PmxEmN9pklGCdLi0Iqg==}
|
resolution: {integrity: sha512-erI3RRZurDr1xES5hvYJ3Imp7jtrXj6f1xYIzDzxiS7nNBufYWPbJwrmMqWC5g9y165PmxEmN9pklGCdLi0Iqg==}
|
||||||
dependencies:
|
dependencies:
|
||||||
'@docsearch/react': 3.6.1(@algolia/client-search@5.2.3)(search-insights@2.17.0)
|
'@docsearch/react': 3.6.1(@algolia/client-search@5.2.4)(search-insights@2.17.1)
|
||||||
preact: 10.23.2
|
preact: 10.23.2
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- '@algolia/client-search'
|
- '@algolia/client-search'
|
||||||
@@ -249,7 +256,7 @@ packages:
|
|||||||
- search-insights
|
- search-insights
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/@docsearch/react@3.6.1(@algolia/client-search@5.2.3)(search-insights@2.17.0):
|
/@docsearch/react@3.6.1(@algolia/client-search@5.2.4)(search-insights@2.17.1):
|
||||||
resolution: {integrity: sha512-qXZkEPvybVhSXj0K7U3bXc233tk5e8PfhoZ6MhPOiik/qUQxYC+Dn9DnoS7CxHQQhHfCvTiN0eY9M12oRghEXw==}
|
resolution: {integrity: sha512-qXZkEPvybVhSXj0K7U3bXc233tk5e8PfhoZ6MhPOiik/qUQxYC+Dn9DnoS7CxHQQhHfCvTiN0eY9M12oRghEXw==}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
'@types/react': '>= 16.8.0 < 19.0.0'
|
'@types/react': '>= 16.8.0 < 19.0.0'
|
||||||
@@ -266,11 +273,11 @@ packages:
|
|||||||
search-insights:
|
search-insights:
|
||||||
optional: true
|
optional: true
|
||||||
dependencies:
|
dependencies:
|
||||||
'@algolia/autocomplete-core': 1.9.3(@algolia/client-search@5.2.3)(algoliasearch@4.24.0)(search-insights@2.17.0)
|
'@algolia/autocomplete-core': 1.9.3(@algolia/client-search@5.2.4)(algoliasearch@4.24.0)(search-insights@2.17.1)
|
||||||
'@algolia/autocomplete-preset-algolia': 1.9.3(@algolia/client-search@5.2.3)(algoliasearch@4.24.0)
|
'@algolia/autocomplete-preset-algolia': 1.9.3(@algolia/client-search@5.2.4)(algoliasearch@4.24.0)
|
||||||
'@docsearch/css': 3.6.1
|
'@docsearch/css': 3.6.1
|
||||||
algoliasearch: 4.24.0
|
algoliasearch: 4.24.0
|
||||||
search-insights: 2.17.0
|
search-insights: 2.17.1
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- '@algolia/client-search'
|
- '@algolia/client-search'
|
||||||
dev: true
|
dev: true
|
||||||
@@ -777,7 +784,7 @@ packages:
|
|||||||
vite: ^5.0.0
|
vite: ^5.0.0
|
||||||
vue: ^3.2.25
|
vue: ^3.2.25
|
||||||
dependencies:
|
dependencies:
|
||||||
vite: 5.4.2
|
vite: 5.4.2(sass-embedded@1.78.0)
|
||||||
vue: 3.4.38
|
vue: 3.4.38
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
@@ -1004,6 +1011,10 @@ packages:
|
|||||||
fill-range: 7.1.1
|
fill-range: 7.1.1
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/buffer-builder@0.2.0:
|
||||||
|
resolution: {integrity: sha512-7VPMEPuYznPSoR21NE1zvd2Xna6c/CloiZCfcMXR1Jny6PjX0N4Nsa38zcBFo/FMK+BlA+FLKbJCQ0i2yxp+Xg==}
|
||||||
|
dev: true
|
||||||
|
|
||||||
/clipboard@2.0.11:
|
/clipboard@2.0.11:
|
||||||
resolution: {integrity: sha512-C+0bbOqkezLIsmWSvlsXS0Q0bmkugu7jcfMIACB+RDEntIzQIkdr148we28AfSloQLRdZlYL/QYyrq05j/3Faw==}
|
resolution: {integrity: sha512-C+0bbOqkezLIsmWSvlsXS0Q0bmkugu7jcfMIACB+RDEntIzQIkdr148we28AfSloQLRdZlYL/QYyrq05j/3Faw==}
|
||||||
dependencies:
|
dependencies:
|
||||||
@@ -1190,10 +1201,19 @@ packages:
|
|||||||
strip-bom-string: 1.0.0
|
strip-bom-string: 1.0.0
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/has-flag@4.0.0:
|
||||||
|
resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==}
|
||||||
|
engines: {node: '>=8'}
|
||||||
|
dev: true
|
||||||
|
|
||||||
/hookable@5.5.3:
|
/hookable@5.5.3:
|
||||||
resolution: {integrity: sha512-Yc+BQe8SvoXH1643Qez1zqLRmbA5rCL+sSmk6TVos0LWVfNIB7PGncdlId77WzLGSIB5KaWgTaNTs2lNVEI6VQ==}
|
resolution: {integrity: sha512-Yc+BQe8SvoXH1643Qez1zqLRmbA5rCL+sSmk6TVos0LWVfNIB7PGncdlId77WzLGSIB5KaWgTaNTs2lNVEI6VQ==}
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/immutable@4.3.7:
|
||||||
|
resolution: {integrity: sha512-1hqclzwYwjRDFLjcFxOM5AYkkG0rpFPpr1RLPMEuGczoS7YA8gLhy8SWXYRAA/XwfEHpfo3cw5JGioS32fnMRw==}
|
||||||
|
dev: true
|
||||||
|
|
||||||
/is-extendable@0.1.1:
|
/is-extendable@0.1.1:
|
||||||
resolution: {integrity: sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==}
|
resolution: {integrity: sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==}
|
||||||
engines: {node: '>=0.10.0'}
|
engines: {node: '>=0.10.0'}
|
||||||
@@ -1406,8 +1426,228 @@ packages:
|
|||||||
queue-microtask: 1.2.3
|
queue-microtask: 1.2.3
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/search-insights@2.17.0:
|
/rxjs@7.8.1:
|
||||||
resolution: {integrity: sha512-AskayU3QNsXQzSL6v4LTYST7NNfs2HWyHHB+sdORP9chsytAhro5XRfToAMI/LAVYgNbzowVZTMfBRodgbUHKg==}
|
resolution: {integrity: sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==}
|
||||||
|
dependencies:
|
||||||
|
tslib: 2.7.0
|
||||||
|
dev: true
|
||||||
|
|
||||||
|
/sass-embedded-android-arm64@1.78.0:
|
||||||
|
resolution: {integrity: sha512-2sAr11EgwPudAuyk4Ite+fWGYJspiFSiZDU2D8/vjjI7BaB9FG6ksYqww3svoMMnjPUWBCjKPDELpZTxViLJbw==}
|
||||||
|
engines: {node: '>=14.0.0'}
|
||||||
|
cpu: [arm64]
|
||||||
|
os: [android]
|
||||||
|
requiresBuild: true
|
||||||
|
dev: true
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
/sass-embedded-android-arm@1.78.0:
|
||||||
|
resolution: {integrity: sha512-YM6nrmKsj+ImaSTd96F+jzbWSbhPkRN4kedbLgIJ5FsILNa9NAqhmrCQz9pdcjuAhyfxWImdUACsT23CPGENZQ==}
|
||||||
|
engines: {node: '>=14.0.0'}
|
||||||
|
cpu: [arm]
|
||||||
|
os: [android]
|
||||||
|
requiresBuild: true
|
||||||
|
dev: true
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
/sass-embedded-android-ia32@1.78.0:
|
||||||
|
resolution: {integrity: sha512-TyJOo4TgnHpOfC/PfqCBqd+jGRanWoRd4Br/0KAfIvaIFjTGIPdk26vUyDVugV1J8QUEY4INGE8EXAuDeRldUQ==}
|
||||||
|
engines: {node: '>=14.0.0'}
|
||||||
|
cpu: [ia32]
|
||||||
|
os: [android]
|
||||||
|
requiresBuild: true
|
||||||
|
dev: true
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
/sass-embedded-android-riscv64@1.78.0:
|
||||||
|
resolution: {integrity: sha512-wwajpsVRuhb7ixrkA3Yu60V2LtROYn45PIYeda30/MrMJi9k3xEqHLhodTexFm6wZoKclGSDZ6L9U5q0XyRKiQ==}
|
||||||
|
engines: {node: '>=14.0.0'}
|
||||||
|
cpu: [riscv64]
|
||||||
|
os: [android]
|
||||||
|
requiresBuild: true
|
||||||
|
dev: true
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
/sass-embedded-android-x64@1.78.0:
|
||||||
|
resolution: {integrity: sha512-k5l66PO0LgSHMDbDzAQ/vqrXMlJ3r42ZHJA8MJvUbA6sQxTzDS381V7L+EhOATwyI225j2FhEeTHW6rr4WBQzA==}
|
||||||
|
engines: {node: '>=14.0.0'}
|
||||||
|
cpu: [x64]
|
||||||
|
os: [android]
|
||||||
|
requiresBuild: true
|
||||||
|
dev: true
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
/sass-embedded-darwin-arm64@1.78.0:
|
||||||
|
resolution: {integrity: sha512-3JaxceFSR6N+a22hPYYkj1p45eBaWTt/M8MPTbfzU3TGZrU9bmRX7WlUVtXTo1yYI2iMf22nCv0PQ5ExFF3FMQ==}
|
||||||
|
engines: {node: '>=14.0.0'}
|
||||||
|
cpu: [arm64]
|
||||||
|
os: [darwin]
|
||||||
|
requiresBuild: true
|
||||||
|
dev: true
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
/sass-embedded-darwin-x64@1.78.0:
|
||||||
|
resolution: {integrity: sha512-UMTijqE3fJ8vEaaD7GPG7G3GsHuPKOdpS8vuA2v2uwO3BPFp/rEKah66atvGqvGO+0JYApkSv0YTnnexSrkHIQ==}
|
||||||
|
engines: {node: '>=14.0.0'}
|
||||||
|
cpu: [x64]
|
||||||
|
os: [darwin]
|
||||||
|
requiresBuild: true
|
||||||
|
dev: true
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
/sass-embedded-linux-arm64@1.78.0:
|
||||||
|
resolution: {integrity: sha512-juMIMpp3DIAiQ842y+boqh0u2SjN4m3mDKrDfMuBznj8DSQoy9J/3e4hLh3g+p0/j83WuROu5nNoYxm2Xz8rww==}
|
||||||
|
engines: {node: '>=14.0.0'}
|
||||||
|
cpu: [arm64]
|
||||||
|
os: [linux]
|
||||||
|
requiresBuild: true
|
||||||
|
dev: true
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
/sass-embedded-linux-arm@1.78.0:
|
||||||
|
resolution: {integrity: sha512-JafT+Co0RK8oO3g9TfVRuG7tkYeh35yDGTgqCFxLrktnkiw5pmIagCfpjxk5GBcSfJMOzhCgclTCDJWAuHGuMQ==}
|
||||||
|
engines: {node: '>=14.0.0'}
|
||||||
|
cpu: [arm]
|
||||||
|
os: [linux]
|
||||||
|
requiresBuild: true
|
||||||
|
dev: true
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
/sass-embedded-linux-ia32@1.78.0:
|
||||||
|
resolution: {integrity: sha512-Gy8GW5g6WX9t8CT2Dto5AL6ikB+pG7aAXWXvfu3RFHktixSwSbyy6CeGqSk1t0xyJCFkQQA/V8HU9bNdeHiBxg==}
|
||||||
|
engines: {node: '>=14.0.0'}
|
||||||
|
cpu: [ia32]
|
||||||
|
os: [linux]
|
||||||
|
requiresBuild: true
|
||||||
|
dev: true
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
/sass-embedded-linux-musl-arm64@1.78.0:
|
||||||
|
resolution: {integrity: sha512-Lu/TlRHbe9aJY7B7PwWCJz7pTT5Rc50VkApWEmPiU/nu0mGbSpg0Xwar6pNeG8+98ubgKKdRb01N3bvclf5a4A==}
|
||||||
|
engines: {node: '>=14.0.0'}
|
||||||
|
cpu: [arm64]
|
||||||
|
os: [linux]
|
||||||
|
requiresBuild: true
|
||||||
|
dev: true
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
/sass-embedded-linux-musl-arm@1.78.0:
|
||||||
|
resolution: {integrity: sha512-DUVXtcsfsiOJ2Zwp4Y3T6KZWX8h0gWpzmFUrx+gSIbg67vV8Ww2DWMjWRwqLe7HOLTYBegMBYpMgMgZiPtXhIA==}
|
||||||
|
engines: {node: '>=14.0.0'}
|
||||||
|
cpu: [arm]
|
||||||
|
os: [linux]
|
||||||
|
requiresBuild: true
|
||||||
|
dev: true
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
/sass-embedded-linux-musl-ia32@1.78.0:
|
||||||
|
resolution: {integrity: sha512-1E5ywUnq6MRPAecr2r/vDOBr93wXyculEmfyF5JRG8mUufMaxGIhfx64OQE6Drjs+EDURcYZ+Qcg6/ubJWqhcw==}
|
||||||
|
engines: {node: '>=14.0.0'}
|
||||||
|
cpu: [ia32]
|
||||||
|
os: [linux]
|
||||||
|
requiresBuild: true
|
||||||
|
dev: true
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
/sass-embedded-linux-musl-riscv64@1.78.0:
|
||||||
|
resolution: {integrity: sha512-YvQEvX7ctn5BwC79+HBagDYIciEkwcl2NLgoydmEsBO/0+ncMKSGnjsn/iRzErbq1KJNyjGEni8eSHlrtQI1vQ==}
|
||||||
|
engines: {node: '>=14.0.0'}
|
||||||
|
cpu: [riscv64]
|
||||||
|
os: [linux]
|
||||||
|
requiresBuild: true
|
||||||
|
dev: true
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
/sass-embedded-linux-musl-x64@1.78.0:
|
||||||
|
resolution: {integrity: sha512-azdUcZZvZmtUBslIKr2/l4aQrTX7BvO96TD0GLdWz9vuXZrokYm09AJZEnb5j6Pk5I4Xr0yM6BG1Vgcbzqi5Zg==}
|
||||||
|
engines: {node: '>=14.0.0'}
|
||||||
|
cpu: [x64]
|
||||||
|
os: [linux]
|
||||||
|
requiresBuild: true
|
||||||
|
dev: true
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
/sass-embedded-linux-riscv64@1.78.0:
|
||||||
|
resolution: {integrity: sha512-g8M6vqHMjZUoH9C1WJsgwu+qmwdJAAMDaJTM1emeAScUZMTaQGzm+Q6C5oSGnAGR3XLT/drgbHhbmruXDgkdeQ==}
|
||||||
|
engines: {node: '>=14.0.0'}
|
||||||
|
cpu: [riscv64]
|
||||||
|
os: [linux]
|
||||||
|
requiresBuild: true
|
||||||
|
dev: true
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
/sass-embedded-linux-x64@1.78.0:
|
||||||
|
resolution: {integrity: sha512-m997ThzpMwql4u6LzZCoHPIQkgK6bbLPLc7ydemo2Wusqzh6j8XAGxVT5oANp6s2Dmj+yh49pKDozal+tzEX9w==}
|
||||||
|
engines: {node: '>=14.0.0'}
|
||||||
|
cpu: [x64]
|
||||||
|
os: [linux]
|
||||||
|
requiresBuild: true
|
||||||
|
dev: true
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
/sass-embedded-win32-arm64@1.78.0:
|
||||||
|
resolution: {integrity: sha512-qTLIIC5URYRmeuYYllfoL0K1cHSUd+f3sFHAA6fjtdgf288usd6ToCbWpuFb0BtVceEfGQX8lEp+teOG7n7Quw==}
|
||||||
|
engines: {node: '>=14.0.0'}
|
||||||
|
cpu: [arm64]
|
||||||
|
os: [win32]
|
||||||
|
requiresBuild: true
|
||||||
|
dev: true
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
/sass-embedded-win32-ia32@1.78.0:
|
||||||
|
resolution: {integrity: sha512-BrOWh18T6Y9xgCokGXElEnd8j03fO4W83bwJ9wHRRkrQWaeHtHs3XWW0fX1j2brngWUTjU+jcYUijWF1Z60krw==}
|
||||||
|
engines: {node: '>=14.0.0'}
|
||||||
|
cpu: [ia32]
|
||||||
|
os: [win32]
|
||||||
|
requiresBuild: true
|
||||||
|
dev: true
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
/sass-embedded-win32-x64@1.78.0:
|
||||||
|
resolution: {integrity: sha512-C14iFDJd7oGhmQehRiEL7GtzMmLwubcDqsBarQ+u9LbHoDlUQfIPd7y8mVtNgtxJCdrAO/jc5qR4C+85yE3xPQ==}
|
||||||
|
engines: {node: '>=14.0.0'}
|
||||||
|
cpu: [x64]
|
||||||
|
os: [win32]
|
||||||
|
requiresBuild: true
|
||||||
|
dev: true
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
/sass-embedded@1.78.0:
|
||||||
|
resolution: {integrity: sha512-NR2kvhWVFABmBm0AqgFw9OweQycs0Qs+/teJ9Su+BUY7up+f8S5F/Zi+7QtAqJlewsQyUNfzm1vRuM+20lBwRQ==}
|
||||||
|
engines: {node: '>=16.0.0'}
|
||||||
|
hasBin: true
|
||||||
|
dependencies:
|
||||||
|
'@bufbuild/protobuf': 1.10.0
|
||||||
|
buffer-builder: 0.2.0
|
||||||
|
immutable: 4.3.7
|
||||||
|
rxjs: 7.8.1
|
||||||
|
supports-color: 8.1.1
|
||||||
|
varint: 6.0.0
|
||||||
|
optionalDependencies:
|
||||||
|
sass-embedded-android-arm: 1.78.0
|
||||||
|
sass-embedded-android-arm64: 1.78.0
|
||||||
|
sass-embedded-android-ia32: 1.78.0
|
||||||
|
sass-embedded-android-riscv64: 1.78.0
|
||||||
|
sass-embedded-android-x64: 1.78.0
|
||||||
|
sass-embedded-darwin-arm64: 1.78.0
|
||||||
|
sass-embedded-darwin-x64: 1.78.0
|
||||||
|
sass-embedded-linux-arm: 1.78.0
|
||||||
|
sass-embedded-linux-arm64: 1.78.0
|
||||||
|
sass-embedded-linux-ia32: 1.78.0
|
||||||
|
sass-embedded-linux-musl-arm: 1.78.0
|
||||||
|
sass-embedded-linux-musl-arm64: 1.78.0
|
||||||
|
sass-embedded-linux-musl-ia32: 1.78.0
|
||||||
|
sass-embedded-linux-musl-riscv64: 1.78.0
|
||||||
|
sass-embedded-linux-musl-x64: 1.78.0
|
||||||
|
sass-embedded-linux-riscv64: 1.78.0
|
||||||
|
sass-embedded-linux-x64: 1.78.0
|
||||||
|
sass-embedded-win32-arm64: 1.78.0
|
||||||
|
sass-embedded-win32-ia32: 1.78.0
|
||||||
|
sass-embedded-win32-x64: 1.78.0
|
||||||
|
dev: true
|
||||||
|
|
||||||
|
/search-insights@2.17.1:
|
||||||
|
resolution: {integrity: sha512-HHFjYH/0AqXacETlIbe9EYc3UNlQYGNNTY0fZ/sWl6SweX+GDxq9NB5+RVoPLgEFuOtCz7M9dhYxqDnhbbF0eQ==}
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/section-matter@1.0.0:
|
/section-matter@1.0.0:
|
||||||
@@ -1467,6 +1707,13 @@ packages:
|
|||||||
copy-anything: 3.0.5
|
copy-anything: 3.0.5
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/supports-color@8.1.1:
|
||||||
|
resolution: {integrity: sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==}
|
||||||
|
engines: {node: '>=10'}
|
||||||
|
dependencies:
|
||||||
|
has-flag: 4.0.0
|
||||||
|
dev: true
|
||||||
|
|
||||||
/tabbable@6.2.0:
|
/tabbable@6.2.0:
|
||||||
resolution: {integrity: sha512-Cat63mxsVJlzYvN51JmVXIgNoUokrIaT2zLclCXjRd8boZ0004U4KCs/sToJ75C6sdlByWxpYnb5Boif1VSFew==}
|
resolution: {integrity: sha512-Cat63mxsVJlzYvN51JmVXIgNoUokrIaT2zLclCXjRd8boZ0004U4KCs/sToJ75C6sdlByWxpYnb5Boif1VSFew==}
|
||||||
dev: true
|
dev: true
|
||||||
@@ -1486,6 +1733,10 @@ packages:
|
|||||||
is-number: 7.0.0
|
is-number: 7.0.0
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/tslib@2.7.0:
|
||||||
|
resolution: {integrity: sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==}
|
||||||
|
dev: true
|
||||||
|
|
||||||
/ufo@1.5.4:
|
/ufo@1.5.4:
|
||||||
resolution: {integrity: sha512-UsUk3byDzKd04EyoZ7U4DOlxQaD14JUKQl6/P7wiX4FNvUfm3XL246n9W5AmqwW5RSFJ27NAuM0iLscAOYUiGQ==}
|
resolution: {integrity: sha512-UsUk3byDzKd04EyoZ7U4DOlxQaD14JUKQl6/P7wiX4FNvUfm3XL246n9W5AmqwW5RSFJ27NAuM0iLscAOYUiGQ==}
|
||||||
dev: true
|
dev: true
|
||||||
@@ -1499,7 +1750,11 @@ packages:
|
|||||||
webpack-virtual-modules: 0.6.2
|
webpack-virtual-modules: 0.6.2
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/vite@5.4.2:
|
/varint@6.0.0:
|
||||||
|
resolution: {integrity: sha512-cXEIW6cfr15lFv563k4GuVuW/fiwjknytD37jIOLSdSWuOI6WnO/oKwmP2FQTU2l01LP8/M5TSAJpzUaGe3uWg==}
|
||||||
|
dev: true
|
||||||
|
|
||||||
|
/vite@5.4.2(sass-embedded@1.78.0):
|
||||||
resolution: {integrity: sha512-dDrQTRHp5C1fTFzcSaMxjk6vdpKvT+2/mIdE07Gw2ykehT49O0z/VHS3zZ8iV/Gh8BJJKHWOe5RjaNrW5xf/GA==}
|
resolution: {integrity: sha512-dDrQTRHp5C1fTFzcSaMxjk6vdpKvT+2/mIdE07Gw2ykehT49O0z/VHS3zZ8iV/Gh8BJJKHWOe5RjaNrW5xf/GA==}
|
||||||
engines: {node: ^18.0.0 || >=20.0.0}
|
engines: {node: ^18.0.0 || >=20.0.0}
|
||||||
hasBin: true
|
hasBin: true
|
||||||
@@ -1533,18 +1788,19 @@ packages:
|
|||||||
esbuild: 0.21.5
|
esbuild: 0.21.5
|
||||||
postcss: 8.4.41
|
postcss: 8.4.41
|
||||||
rollup: 4.21.2
|
rollup: 4.21.2
|
||||||
|
sass-embedded: 1.78.0
|
||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
fsevents: 2.3.3
|
fsevents: 2.3.3
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/vitepress-sidebar@1.25.0:
|
/vitepress-sidebar@1.25.3:
|
||||||
resolution: {integrity: sha512-hbS6DEQjdZS1lbm8p1AKrzdfoFDf4Eas/Dmr1xbN+yv9XVf6xAW+q4tJINmuAt6vnvkEgylZlcH1PGzKX0RgcA==}
|
resolution: {integrity: sha512-NyfJAHqN2AnFEqzVPTQJVo/ii++8i13Xa6W0rqyOqJ4vjZVxkX8HSUUuwcE3ib4COon0lArLJhdQmnVKQvq5mA==}
|
||||||
engines: {node: '>=18.0.0'}
|
engines: {node: '>=18.0.0'}
|
||||||
dependencies:
|
dependencies:
|
||||||
gray-matter: 4.0.3
|
gray-matter: 4.0.3
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/vitepress@1.3.4(@algolia/client-search@5.2.3)(search-insights@2.17.0):
|
/vitepress@1.3.4(@algolia/client-search@5.2.4)(sass-embedded@1.78.0)(search-insights@2.17.1):
|
||||||
resolution: {integrity: sha512-I1/F6OW1xl3kW4PaIMC6snxjWgf3qfziq2aqsDoFc/Gt41WbcRv++z8zjw8qGRIJ+I4bUW7ZcKFDHHN/jkH9DQ==}
|
resolution: {integrity: sha512-I1/F6OW1xl3kW4PaIMC6snxjWgf3qfziq2aqsDoFc/Gt41WbcRv++z8zjw8qGRIJ+I4bUW7ZcKFDHHN/jkH9DQ==}
|
||||||
hasBin: true
|
hasBin: true
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
@@ -1557,7 +1813,7 @@ packages:
|
|||||||
optional: true
|
optional: true
|
||||||
dependencies:
|
dependencies:
|
||||||
'@docsearch/css': 3.6.1
|
'@docsearch/css': 3.6.1
|
||||||
'@docsearch/js': 3.6.1(@algolia/client-search@5.2.3)(search-insights@2.17.0)
|
'@docsearch/js': 3.6.1(@algolia/client-search@5.2.4)(search-insights@2.17.1)
|
||||||
'@shikijs/core': 1.15.1
|
'@shikijs/core': 1.15.1
|
||||||
'@shikijs/transformers': 1.15.1
|
'@shikijs/transformers': 1.15.1
|
||||||
'@types/markdown-it': 14.1.2
|
'@types/markdown-it': 14.1.2
|
||||||
@@ -1570,7 +1826,7 @@ packages:
|
|||||||
mark.js: 8.11.1
|
mark.js: 8.11.1
|
||||||
minisearch: 7.1.0
|
minisearch: 7.1.0
|
||||||
shiki: 1.15.1
|
shiki: 1.15.1
|
||||||
vite: 5.4.2
|
vite: 5.4.2(sass-embedded@1.78.0)
|
||||||
vue: 3.4.38
|
vue: 3.4.38
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- '@algolia/client-search'
|
- '@algolia/client-search'
|
||||||
|
@@ -52,5 +52,26 @@
|
|||||||
"author": "snowykami",
|
"author": "snowykami",
|
||||||
"description": "自定义各种卡片的背景",
|
"description": "自定义各种卡片的背景",
|
||||||
"link": "https://cdn.liteyuki.icu/static/lrp/morebg.zip"
|
"link": "https://cdn.liteyuki.icu/static/lrp/morebg.zip"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "测试资源包",
|
||||||
|
"desc": "test",
|
||||||
|
"link": "https://cdn.liteyuki.icu/static/lrp/liteyuki_words_aojiao.zip",
|
||||||
|
"homepage": "",
|
||||||
|
"author": "snowykami"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "轻雪Kakyo语言包 稳定版",
|
||||||
|
"description": "Liteyuki Bot的语言包,用于提供多种语言的翻译。",
|
||||||
|
"link": "https://cdn.liteyuki.icu/static/lrp/kakyo.zip",
|
||||||
|
"homepage": "https://github.com/Nanaloveyuki/liteyuki-langpack",
|
||||||
|
"author": "Nanaloveyuki"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "测试资源包2",
|
||||||
|
"description": "test",
|
||||||
|
"link": "https://cdn.liteyuki.icu/static/lrp/liteyuki_words_aojiao.zip",
|
||||||
|
"homepage": "",
|
||||||
|
"author": "snowykami"
|
||||||
}
|
}
|
||||||
]
|
]
|
@@ -10,7 +10,8 @@ order: 1
|
|||||||
|
|
||||||
```bash
|
```bash
|
||||||
# 克隆项目到本地,轻雪使用Git进行版本管理,该步骤为必要项
|
# 克隆项目到本地,轻雪使用Git进行版本管理,该步骤为必要项
|
||||||
git clone https://github.com/LiteyukiStudio/LiteyukiBot --depth=1
|
git clone https://github.com/LiteyukiStudio/LiteyukiBot --depth=1 # 若你不能访问Github,可以使用Liteyuki镜像:https://git.liteyuki.icu/LiteyukiStudio/LiteyukiBot
|
||||||
|
|
||||||
# 切换到Bot目录下
|
# 切换到Bot目录下
|
||||||
cd LiteyukiBot
|
cd LiteyukiBot
|
||||||
# 安装依赖
|
# 安装依赖
|
||||||
|
21
docs/zh/dev/best_practices.md
Normal file
21
docs/zh/dev/best_practices.md
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
---
|
||||||
|
title: 最佳实践
|
||||||
|
order: 10
|
||||||
|
---
|
||||||
|
|
||||||
|
# 最佳实践
|
||||||
|
|
||||||
|
## 机器人应用
|
||||||
|
- [LiteyukiBot](https://github.com/LiteyukiStudio/LiteyukiBot):轻雪官方机器人
|
||||||
|
- [LiteyukiBot-TriM](https://github.com/TriM-Organization/LiteyukiBot-TriM):TriM 官方定制轻雪机器人
|
||||||
|
- [Liteyuki Marsho](https://git.liteyuki.icu/LiteyukiStudio/marsho-alpha):基于 轻雪 和 github model 的可爱猫娘机器人
|
||||||
|
|
||||||
|
## 插件
|
||||||
|
- [liteyukibot-plugin-nonebot](https://github.com/LiteyukiStudio/liteyukibot-plugin-nonebot):轻雪机器人 NoneBot 插件,让轻雪支持 NoneBot
|
||||||
|
- [nonebot-plugin-liteyukibot](https://github.com/LiteyukiStudio/nonebot-plugin-liteyukibot):NoneBot 插件,让 NoneBot 支持轻雪
|
||||||
|
|
||||||
|
## 其他
|
||||||
|
- [liteyuki starmap](https://starmap.liteyuki.icu):轻雪官方星图,展示轻雪的所有实例及其位置分布
|
||||||
|
- [TRSS_Liteyuki](https://timerainstarsky.github.io/TRSS_Liteyuki/):TRSS LiteyukiBot 管理脚本
|
||||||
|
- [litedoc](https://github.com/LiteyukiStudio/litedoc):轻雪API文档生成器
|
||||||
|
- liteyukibot-api (闭源):轻雪机器人统计接口
|
@@ -2,6 +2,13 @@
|
|||||||
title: 开发指南
|
title: 开发指南
|
||||||
order: 0
|
order: 0
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import ContributorBar from '../../components/ContributorBar.vue'
|
||||||
|
</script>
|
||||||
|
|
||||||
|
|
||||||
# 开发指南
|
# 开发指南
|
||||||
|
|
||||||
## 如何开发
|
## 如何开发
|
||||||
@@ -49,8 +56,8 @@ order: 0
|
|||||||
- commit message请遵循以下规范:
|
- commit message请遵循以下规范:
|
||||||
- 应在每次完成一个功能或修复一个bug后提交代码,不要将多个功能或多个bug的代码混在一起提交。
|
- 应在每次完成一个功能或修复一个bug后提交代码,不要将多个功能或多个bug的代码混在一起提交。
|
||||||
- 我们使用gitmoji来标记commit的类型,如`:sparkles:`表示引入新功能,`:bug:`表示修复bug等,具体请参考[gitmoji](https://gitmoji.dev/)
|
- 我们使用gitmoji来标记commit的类型,如`:sparkles:`表示引入新功能,`:bug:`表示修复bug等,具体请参考[gitmoji](https://gitmoji.dev/)
|
||||||
- commit message的格式为`<emoji> [module]: <message>`,如`:sparkles: [liteyuki.event]: add new feature`,
|
- commit message的格式为`<emoji> [type:] <message>`,如`:sparkles: feat: 给event添加新字段`,
|
||||||
其中module字段为受影响部分,例如`liteyuki.message`,`docs.en.guide.md`等,不作过多要求,但请尽量填写;message字段为简短的描述,总结来说就是你干了什么。
|
其中`type`字段为commit类型且**可选**,message字段为简短的描述,总结来说就是你干了什么。
|
||||||
- 不限制commit message的语言,有条件可以使用中英双语。
|
- 不限制commit message的语言,有条件可以使用中英双语。
|
||||||
- 文档请遵循[`Markdown`](https://www.markdownguide.org/)语法,并且支持vitepress相关内容:
|
- 文档请遵循[`Markdown`](https://www.markdownguide.org/)语法,并且支持vitepress相关内容:
|
||||||
- 修订文档时,每个语言的文档都要修订。
|
- 修订文档时,每个语言的文档都要修订。
|
||||||
@@ -59,3 +66,6 @@ order: 0
|
|||||||
|
|
||||||
## 最后
|
## 最后
|
||||||
- 本项目是一个非盈利的开源项目,我们欢迎任何人参与开发,你的贡献将会使轻雪变得更好。
|
- 本项目是一个非盈利的开源项目,我们欢迎任何人参与开发,你的贡献将会使轻雪变得更好。
|
||||||
|
|
||||||
|
|
||||||
|
<ContributorBar />
|
||||||
|
@@ -14,6 +14,9 @@ hero:
|
|||||||
- theme: alt
|
- theme: alt
|
||||||
text: 📦 扩展
|
text: 📦 扩展
|
||||||
link: ./store/resource
|
link: ./store/resource
|
||||||
|
- theme: alt
|
||||||
|
text: 🛠️ 开发
|
||||||
|
link: ./dev/guide
|
||||||
image:
|
image:
|
||||||
light: ./liteyuki.svg
|
light: ./liteyuki.svg
|
||||||
dark: ./liteyuki-dark.svg
|
dark: ./liteyuki-dark.svg
|
||||||
@@ -23,7 +26,7 @@ features:
|
|||||||
- title: 生态良好
|
- title: 生态良好
|
||||||
icon: 🛠️
|
icon: 🛠️
|
||||||
details: 基于轻雪框架,原生支持任意Python Bot框架和应用程序
|
details: 基于轻雪框架,原生支持任意Python Bot框架和应用程序
|
||||||
link: ./dev/api/api
|
link: ./dev/api
|
||||||
|
|
||||||
- title: 插件管理
|
- title: 插件管理
|
||||||
icon: 🧩
|
icon: 🧩
|
||||||
|
@@ -8,18 +8,21 @@ import threading
|
|||||||
import time
|
import time
|
||||||
from typing import Any, Optional
|
from typing import Any, Optional
|
||||||
|
|
||||||
from liteyuki.bot.lifespan import (LIFESPAN_FUNC, Lifespan, PROCESS_LIFESPAN_FUNC)
|
from liteyuki.bot.lifespan import LIFESPAN_FUNC, Lifespan, PROCESS_LIFESPAN_FUNC
|
||||||
from liteyuki.comm.channel import get_channel
|
from liteyuki.comm.channel import get_channel
|
||||||
from liteyuki.core.manager import ProcessManager
|
from liteyuki.core.manager import ProcessManager
|
||||||
from liteyuki.log import init_log, logger
|
from liteyuki.log import init_log, logger
|
||||||
from liteyuki.plugin import load_plugin
|
from liteyuki.plugin import load_plugin
|
||||||
from liteyuki.utils import IS_MAIN_PROCESS
|
from liteyuki.utils import IS_MAIN_PROCESS
|
||||||
|
|
||||||
|
# new version
|
||||||
|
from liteyuki.core.manager import sub_process_manager
|
||||||
|
|
||||||
__all__ = [
|
__all__ = [
|
||||||
"LiteyukiBot",
|
"LiteyukiBot",
|
||||||
"get_bot",
|
"get_bot",
|
||||||
"get_config",
|
"get_config",
|
||||||
"get_config_with_compat",
|
"get_config_with_compat",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
@@ -60,6 +63,7 @@ class LiteyukiBot:
|
|||||||
启动逻辑
|
启动逻辑
|
||||||
"""
|
"""
|
||||||
await self.lifespan.before_start() # 启动前钩子
|
await self.lifespan.before_start() # 启动前钩子
|
||||||
|
sub_process_manager.start_all()
|
||||||
await self.lifespan.after_start() # 启动后钩子
|
await self.lifespan.after_start() # 启动后钩子
|
||||||
await self.keep_alive()
|
await self.keep_alive()
|
||||||
|
|
||||||
@@ -108,7 +112,11 @@ class LiteyukiBot:
|
|||||||
cmd = "nohup"
|
cmd = "nohup"
|
||||||
self.process_manager.terminate_all()
|
self.process_manager.terminate_all()
|
||||||
# 进程退出后重启
|
# 进程退出后重启
|
||||||
threading.Thread(target=os.system, args=(f"{cmd} {executable} {' '.join(args)}",), daemon=True).start()
|
threading.Thread(
|
||||||
|
target=os.system,
|
||||||
|
args=(f"{cmd} {executable} {' '.join(args)}",),
|
||||||
|
daemon=True,
|
||||||
|
).start()
|
||||||
sys.exit(0)
|
sys.exit(0)
|
||||||
self.call_restart_count += 1
|
self.call_restart_count += 1
|
||||||
|
|
||||||
@@ -189,7 +197,9 @@ class LiteyukiBot:
|
|||||||
"""
|
"""
|
||||||
return self.lifespan.on_before_process_shutdown(func)
|
return self.lifespan.on_before_process_shutdown(func)
|
||||||
|
|
||||||
def on_before_process_restart(self, func: PROCESS_LIFESPAN_FUNC) -> PROCESS_LIFESPAN_FUNC:
|
def on_before_process_restart(
|
||||||
|
self, func: PROCESS_LIFESPAN_FUNC
|
||||||
|
) -> PROCESS_LIFESPAN_FUNC:
|
||||||
"""
|
"""
|
||||||
注册进程重启前的函数,为子进程重启时调用
|
注册进程重启前的函数,为子进程重启时调用
|
||||||
Args:
|
Args:
|
||||||
@@ -211,7 +221,7 @@ class LiteyukiBot:
|
|||||||
return self.lifespan.on_after_restart(func)
|
return self.lifespan.on_after_restart(func)
|
||||||
|
|
||||||
|
|
||||||
_BOT_INSTANCE: LiteyukiBot
|
_BOT_INSTANCE: LiteyukiBot | None = None
|
||||||
|
|
||||||
|
|
||||||
def get_bot() -> LiteyukiBot:
|
def get_bot() -> LiteyukiBot:
|
||||||
@@ -241,7 +251,9 @@ def get_config(key: str, default: Any = None) -> Any:
|
|||||||
return get_bot().config.get(key, default)
|
return get_bot().config.get(key, default)
|
||||||
|
|
||||||
|
|
||||||
def get_config_with_compat(key: str, compat_keys: tuple[str], default: Any = None) -> Any:
|
def get_config_with_compat(
|
||||||
|
key: str, compat_keys: tuple[str], default: Any = None
|
||||||
|
) -> Any:
|
||||||
"""
|
"""
|
||||||
获取配置,兼容旧版本
|
获取配置,兼容旧版本
|
||||||
Args:
|
Args:
|
||||||
@@ -256,14 +268,18 @@ def get_config_with_compat(key: str, compat_keys: tuple[str], default: Any = Non
|
|||||||
return get_bot().config[key]
|
return get_bot().config[key]
|
||||||
for compat_key in compat_keys:
|
for compat_key in compat_keys:
|
||||||
if compat_key in get_bot().config:
|
if compat_key in get_bot().config:
|
||||||
logger.warning(f"Config key \"{compat_key}\" will be deprecated, use \"{key}\" instead.")
|
logger.warning(
|
||||||
|
f'Config key "{compat_key}" will be deprecated, use "{key}" instead.'
|
||||||
|
)
|
||||||
return get_bot().config[compat_key]
|
return get_bot().config[compat_key]
|
||||||
return default
|
return default
|
||||||
|
|
||||||
|
|
||||||
def print_logo():
|
def print_logo():
|
||||||
"""@litedoc-hide"""
|
"""@litedoc-hide"""
|
||||||
print("\033[34m" + r"""
|
print(
|
||||||
|
"\033[34m"
|
||||||
|
+ r"""
|
||||||
__ ______ ________ ________ __ __ __ __ __ __ ______
|
__ ______ ________ ________ __ __ __ __ __ __ ______
|
||||||
/ | / |/ |/ |/ \ / |/ | / |/ | / |/ |
|
/ | / |/ |/ |/ \ / |/ | / |/ | / |/ |
|
||||||
$$ | $$$$$$/ $$$$$$$$/ $$$$$$$$/ $$ \ /$$/ $$ | $$ |$$ | /$$/ $$$$$$/
|
$$ | $$$$$$/ $$$$$$$$/ $$$$$$$$/ $$ \ /$$/ $$ | $$ |$$ | /$$/ $$$$$$/
|
||||||
@@ -273,4 +289,6 @@ def print_logo():
|
|||||||
$$ |_____ _$$ |_ $$ | $$ |_____ $$ | $$ \__$$ |$$ |$$ \ _$$ |_
|
$$ |_____ _$$ |_ $$ | $$ |_____ $$ | $$ \__$$ |$$ |$$ \ _$$ |_
|
||||||
$$ |/ $$ | $$ | $$ | $$ | $$ $$/ $$ | $$ |/ $$ |
|
$$ |/ $$ | $$ | $$ | $$ | $$ $$/ $$ | $$ |/ $$ |
|
||||||
$$$$$$$$/ $$$$$$/ $$/ $$$$$$$$/ $$/ $$$$$$/ $$/ $$/ $$$$$$/
|
$$$$$$$$/ $$$$$$/ $$/ $$$$$$$$/ $$/ $$$$$$/ $$/ $$/ $$$$$$/
|
||||||
""" + "\033[0m")
|
"""
|
||||||
|
+ "\033[0m"
|
||||||
|
)
|
||||||
|
@@ -4,20 +4,31 @@
|
|||||||
"""
|
"""
|
||||||
import asyncio
|
import asyncio
|
||||||
from multiprocessing import Pipe
|
from multiprocessing import Pipe
|
||||||
from typing import Any, Callable, Coroutine, Generic, Optional, TypeAlias, TypeVar, get_args
|
from typing import (
|
||||||
|
Any,
|
||||||
|
Callable,
|
||||||
|
Coroutine,
|
||||||
|
Generic,
|
||||||
|
Optional,
|
||||||
|
TypeAlias,
|
||||||
|
TypeVar,
|
||||||
|
get_args,
|
||||||
|
)
|
||||||
|
|
||||||
from liteyuki.log import logger
|
from liteyuki.log import logger
|
||||||
from liteyuki.utils import IS_MAIN_PROCESS, is_coroutine_callable
|
from liteyuki.utils import IS_MAIN_PROCESS, is_coroutine_callable
|
||||||
|
|
||||||
T = TypeVar("T")
|
T = TypeVar("T")
|
||||||
|
|
||||||
SYNC_ON_RECEIVE_FUNC: TypeAlias = Callable[[T], Any] # 同步接收函数
|
SYNC_ON_RECEIVE_FUNC: TypeAlias = Callable[[T], Any] # 同步接收函数
|
||||||
ASYNC_ON_RECEIVE_FUNC: TypeAlias = Callable[[T], Coroutine[Any, Any, Any]] # 异步接收函数
|
ASYNC_ON_RECEIVE_FUNC: TypeAlias = Callable[
|
||||||
ON_RECEIVE_FUNC: TypeAlias = SYNC_ON_RECEIVE_FUNC | ASYNC_ON_RECEIVE_FUNC # 接收函数
|
[T], Coroutine[Any, Any, Any]
|
||||||
|
] # 异步接收函数
|
||||||
|
ON_RECEIVE_FUNC: TypeAlias = SYNC_ON_RECEIVE_FUNC | ASYNC_ON_RECEIVE_FUNC # 接收函数
|
||||||
|
|
||||||
SYNC_FILTER_FUNC: TypeAlias = Callable[[T], bool] # 同步过滤函数
|
SYNC_FILTER_FUNC: TypeAlias = Callable[[T], bool] # 同步过滤函数
|
||||||
ASYNC_FILTER_FUNC: TypeAlias = Callable[[T], Coroutine[Any, Any, bool]] # 异步过滤函数
|
ASYNC_FILTER_FUNC: TypeAlias = Callable[[T], Coroutine[Any, Any, bool]] # 异步过滤函数
|
||||||
FILTER_FUNC: TypeAlias = SYNC_FILTER_FUNC | ASYNC_FILTER_FUNC # 过滤函数
|
FILTER_FUNC: TypeAlias = SYNC_FILTER_FUNC | ASYNC_FILTER_FUNC # 过滤函数
|
||||||
|
|
||||||
_func_id: int = 0
|
_func_id: int = 0
|
||||||
_channel: dict[str, "Channel"] = {}
|
_channel: dict[str, "Channel"] = {}
|
||||||
@@ -39,7 +50,9 @@ class Channel(Generic[T]):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
self.conn_send, self.conn_recv = Pipe()
|
self.conn_send, self.conn_recv = Pipe()
|
||||||
self._conn_send_inner, self._conn_recv_inner = Pipe() # 内部通道,用于子进程通信
|
self._conn_send_inner, self._conn_recv_inner = (
|
||||||
|
Pipe()
|
||||||
|
) # 内部通道,用于子进程通信
|
||||||
self._closed = False
|
self._closed = False
|
||||||
self._on_main_receive_func_ids: list[int] = []
|
self._on_main_receive_func_ids: list[int] = []
|
||||||
self._on_sub_receive_func_ids: list[int] = []
|
self._on_sub_receive_func_ids: list[int] = []
|
||||||
@@ -64,7 +77,9 @@ class Channel(Generic[T]):
|
|||||||
_channel[name] = self
|
_channel[name] = self
|
||||||
logger.debug(f"Channel {name} initialized in main process")
|
logger.debug(f"Channel {name} initialized in main process")
|
||||||
else:
|
else:
|
||||||
logger.debug(f"Channel {name} initialized in sub process, should manually set in main process")
|
logger.debug(
|
||||||
|
f"Channel {name} initialized in sub process, should manually set in main process"
|
||||||
|
)
|
||||||
|
|
||||||
def _get_generic_type(self) -> Optional[type]:
|
def _get_generic_type(self) -> Optional[type]:
|
||||||
"""
|
"""
|
||||||
@@ -72,7 +87,7 @@ class Channel(Generic[T]):
|
|||||||
Returns:
|
Returns:
|
||||||
Optional[type]: 泛型类型
|
Optional[type]: 泛型类型
|
||||||
"""
|
"""
|
||||||
if hasattr(self, '__orig_class__'):
|
if hasattr(self, "__orig_class__"):
|
||||||
return get_args(self.__orig_class__)[0]
|
return get_args(self.__orig_class__)[0]
|
||||||
return None
|
return None
|
||||||
|
|
||||||
@@ -98,7 +113,10 @@ class Channel(Generic[T]):
|
|||||||
elif isinstance(structure, dict):
|
elif isinstance(structure, dict):
|
||||||
if not isinstance(data, dict):
|
if not isinstance(data, dict):
|
||||||
return False
|
return False
|
||||||
return all(k in data and self._validate_structure(data[k], structure[k]) for k in structure)
|
return all(
|
||||||
|
k in data and self._validate_structure(data[k], structure[k])
|
||||||
|
for k in structure
|
||||||
|
)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
@@ -113,10 +131,12 @@ class Channel(Generic[T]):
|
|||||||
if self.type_check:
|
if self.type_check:
|
||||||
_type = self._get_generic_type()
|
_type = self._get_generic_type()
|
||||||
if _type is not None and not self._validate_structure(data, _type):
|
if _type is not None and not self._validate_structure(data, _type):
|
||||||
raise TypeError(f"Data must be an instance of {_type}, {type(data)} found")
|
raise TypeError(
|
||||||
|
f"Data must be an instance of {_type}, {type(data)} found"
|
||||||
|
)
|
||||||
|
|
||||||
if self._closed:
|
if self._closed:
|
||||||
raise RuntimeError("Cannot send to a closed channel_")
|
raise RuntimeError("Cannot send to a closed channel")
|
||||||
self.conn_send.send(data)
|
self.conn_send.send(data)
|
||||||
|
|
||||||
def receive(self) -> T:
|
def receive(self) -> T:
|
||||||
@@ -126,7 +146,7 @@ class Channel(Generic[T]):
|
|||||||
T: 数据
|
T: 数据
|
||||||
"""
|
"""
|
||||||
if self._closed:
|
if self._closed:
|
||||||
raise RuntimeError("Cannot receive from a closed channel_")
|
raise RuntimeError("Cannot receive from a closed channel")
|
||||||
|
|
||||||
while True:
|
while True:
|
||||||
data = self.conn_recv.recv()
|
data = self.conn_recv.recv()
|
||||||
@@ -142,7 +162,9 @@ class Channel(Generic[T]):
|
|||||||
data = await loop.run_in_executor(None, self.receive)
|
data = await loop.run_in_executor(None, self.receive)
|
||||||
return data
|
return data
|
||||||
|
|
||||||
def on_receive(self, filter_func: Optional[FILTER_FUNC] = None) -> Callable[[Callable[[T], Any]], Callable[[T], Any]]:
|
def on_receive(
|
||||||
|
self, filter_func: Optional[FILTER_FUNC] = None
|
||||||
|
) -> Callable[[Callable[[T], Any]], Callable[[T], Any]]:
|
||||||
"""
|
"""
|
||||||
接收数据并执行函数
|
接收数据并执行函数
|
||||||
Args:
|
Args:
|
||||||
@@ -187,37 +209,52 @@ class Channel(Generic[T]):
|
|||||||
data: 数据
|
data: 数据
|
||||||
"""
|
"""
|
||||||
if IS_MAIN_PROCESS:
|
if IS_MAIN_PROCESS:
|
||||||
[asyncio.create_task(_callback_funcs[func_id](data)) for func_id in self._on_main_receive_func_ids]
|
[
|
||||||
|
asyncio.create_task(_callback_funcs[func_id](data))
|
||||||
|
for func_id in self._on_main_receive_func_ids
|
||||||
|
]
|
||||||
else:
|
else:
|
||||||
[asyncio.create_task(_callback_funcs[func_id](data)) for func_id in self._on_sub_receive_func_ids]
|
[
|
||||||
|
asyncio.create_task(_callback_funcs[func_id](data))
|
||||||
|
for func_id in self._on_sub_receive_func_ids
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
"""子进程可用的主动和被动通道"""
|
"""子进程可用的主动和被动通道"""
|
||||||
active_channel: Channel = Channel(name="active_channel") # 主动通道
|
active_channel: Channel = Channel(name="active_channel") # 主动通道
|
||||||
passive_channel: Channel = Channel(name="passive_channel") # 被动通道
|
passive_channel: Channel = Channel(name="passive_channel") # 被动通道
|
||||||
publish_channel: Channel[tuple[str, dict[str, Any]]] = Channel(name="publish_channel") # 发布通道
|
publish_channel: Channel[tuple[str, dict[str, Any]]] = Channel(
|
||||||
|
name="publish_channel"
|
||||||
|
) # 发布通道
|
||||||
"""通道传递通道,主进程创建单例,子进程初始化时实例化"""
|
"""通道传递通道,主进程创建单例,子进程初始化时实例化"""
|
||||||
channel_deliver_active_channel: Channel[Channel[Any]] # 主动通道传递通道
|
channel_deliver_active_channel: Channel[Channel[Any]] # 主动通道传递通道
|
||||||
channel_deliver_passive_channel: Channel[tuple[str, dict[str, Any]]] # 被动通道传递通道
|
channel_deliver_passive_channel: Channel[tuple[str, dict[str, Any]]] # 被动通道传递通道
|
||||||
|
|
||||||
if IS_MAIN_PROCESS:
|
if IS_MAIN_PROCESS:
|
||||||
channel_deliver_active_channel = Channel(name="channel_deliver_active_channel") # 主动通道传递通道
|
channel_deliver_active_channel = Channel(
|
||||||
channel_deliver_passive_channel = Channel(name="channel_deliver_passive_channel") # 被动通道传递通道
|
name="channel_deliver_active_channel"
|
||||||
|
) # 主动通道传递通道
|
||||||
|
channel_deliver_passive_channel = Channel(
|
||||||
|
name="channel_deliver_passive_channel"
|
||||||
|
) # 被动通道传递通道
|
||||||
|
|
||||||
|
@channel_deliver_passive_channel.on_receive(
|
||||||
@channel_deliver_passive_channel.on_receive(filter_func=lambda data: data[0] == "set_channel")
|
filter_func=lambda data: data[0] == "set_channel"
|
||||||
|
)
|
||||||
def on_set_channel(data: tuple[str, dict[str, Any]]):
|
def on_set_channel(data: tuple[str, dict[str, Any]]):
|
||||||
name, channel = data[1]["name"], data[1]["channel_"]
|
name, channel = data[1]["name"], data[1]["channel_"]
|
||||||
set_channel(name, channel)
|
set_channel(name, channel)
|
||||||
|
|
||||||
|
@channel_deliver_passive_channel.on_receive(
|
||||||
@channel_deliver_passive_channel.on_receive(filter_func=lambda data: data[0] == "get_channel")
|
filter_func=lambda data: data[0] == "get_channel"
|
||||||
|
)
|
||||||
def on_get_channel(data: tuple[str, dict[str, Any]]):
|
def on_get_channel(data: tuple[str, dict[str, Any]]):
|
||||||
name, recv_chan = data[1]["name"], data[1]["recv_chan"]
|
name, recv_chan = data[1]["name"], data[1]["recv_chan"]
|
||||||
recv_chan.send(get_channel(name))
|
recv_chan.send(get_channel(name))
|
||||||
|
|
||||||
|
@channel_deliver_passive_channel.on_receive(
|
||||||
@channel_deliver_passive_channel.on_receive(filter_func=lambda data: data[0] == "get_channels")
|
filter_func=lambda data: data[0] == "get_channels"
|
||||||
|
)
|
||||||
def on_get_channels(data: tuple[str, dict[str, Any]]):
|
def on_get_channels(data: tuple[str, dict[str, Any]]):
|
||||||
recv_chan = data[1]["recv_chan"]
|
recv_chan = data[1]["recv_chan"]
|
||||||
recv_chan.send(get_channels())
|
recv_chan.send(get_channels())
|
||||||
@@ -231,7 +268,9 @@ def set_channel(name: str, channel: "Channel"):
|
|||||||
channel ([`Channel`](#class-channel-generic-t)): 通道实例
|
channel ([`Channel`](#class-channel-generic-t)): 通道实例
|
||||||
"""
|
"""
|
||||||
if not isinstance(channel, Channel):
|
if not isinstance(channel, Channel):
|
||||||
raise TypeError(f"channel_ must be an instance of Channel, {type(channel)} found")
|
raise TypeError(
|
||||||
|
f"channel_ must be an instance of Channel, {type(channel)} found"
|
||||||
|
)
|
||||||
|
|
||||||
if IS_MAIN_PROCESS:
|
if IS_MAIN_PROCESS:
|
||||||
if name in _channel:
|
if name in _channel:
|
||||||
@@ -241,10 +280,11 @@ def set_channel(name: str, channel: "Channel"):
|
|||||||
# 请求主进程设置通道
|
# 请求主进程设置通道
|
||||||
channel_deliver_passive_channel.send(
|
channel_deliver_passive_channel.send(
|
||||||
(
|
(
|
||||||
"set_channel", {
|
"set_channel",
|
||||||
"name" : name,
|
{
|
||||||
"channel_": channel,
|
"name": name,
|
||||||
}
|
"channel_": channel,
|
||||||
|
},
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -273,13 +313,7 @@ def get_channel(name: str) -> "Channel":
|
|||||||
else:
|
else:
|
||||||
recv_chan = Channel[Channel[Any]]("recv_chan")
|
recv_chan = Channel[Channel[Any]]("recv_chan")
|
||||||
channel_deliver_passive_channel.send(
|
channel_deliver_passive_channel.send(
|
||||||
(
|
("get_channel", {"name": name, "recv_chan": recv_chan})
|
||||||
"get_channel",
|
|
||||||
{
|
|
||||||
"name" : name,
|
|
||||||
"recv_chan": recv_chan
|
|
||||||
}
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
return recv_chan.receive()
|
return recv_chan.receive()
|
||||||
|
|
||||||
@@ -294,12 +328,5 @@ def get_channels() -> dict[str, "Channel"]:
|
|||||||
return _channel
|
return _channel
|
||||||
else:
|
else:
|
||||||
recv_chan = Channel[dict[str, Channel[Any]]]("recv_chan")
|
recv_chan = Channel[dict[str, Channel[Any]]]("recv_chan")
|
||||||
channel_deliver_passive_channel.send(
|
channel_deliver_passive_channel.send(("get_channels", {"recv_chan": recv_chan}))
|
||||||
(
|
|
||||||
"get_channels",
|
|
||||||
{
|
|
||||||
"recv_chan": recv_chan
|
|
||||||
}
|
|
||||||
)
|
|
||||||
)
|
|
||||||
return recv_chan.receive()
|
return recv_chan.receive()
|
||||||
|
@@ -1,26 +0,0 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
"""
|
|
||||||
本模块用于实现RPC(基于IPC)通信
|
|
||||||
"""
|
|
||||||
|
|
||||||
from typing import TypeAlias, Callable, Any
|
|
||||||
|
|
||||||
from liteyuki.comm.channel import Channel
|
|
||||||
|
|
||||||
ON_CALLING_FUNC: TypeAlias = Callable[[tuple, dict], Any]
|
|
||||||
|
|
||||||
|
|
||||||
class RPC:
|
|
||||||
"""
|
|
||||||
RPC类
|
|
||||||
"""
|
|
||||||
|
|
||||||
def __init__(self, on_calling: ON_CALLING_FUNC) -> None:
|
|
||||||
self.on_calling = on_calling
|
|
||||||
|
|
||||||
def call(self, args: tuple, kwargs: dict) -> Any:
|
|
||||||
"""
|
|
||||||
调用
|
|
||||||
"""
|
|
||||||
# 获取self.calling函数名
|
|
||||||
return self.on_calling(args, kwargs)
|
|
@@ -14,6 +14,9 @@ import threading
|
|||||||
from multiprocessing import Process
|
from multiprocessing import Process
|
||||||
from typing import Any, Callable, TYPE_CHECKING, TypeAlias
|
from typing import Any, Callable, TYPE_CHECKING, TypeAlias
|
||||||
|
|
||||||
|
from croterline.context import Context
|
||||||
|
from croterline.process import SubProcess, ProcessFuncType
|
||||||
|
|
||||||
from liteyuki.log import logger
|
from liteyuki.log import logger
|
||||||
from liteyuki.utils import IS_MAIN_PROCESS
|
from liteyuki.utils import IS_MAIN_PROCESS
|
||||||
|
|
||||||
@@ -26,7 +29,10 @@ from liteyuki.comm import Channel
|
|||||||
if IS_MAIN_PROCESS:
|
if IS_MAIN_PROCESS:
|
||||||
from liteyuki.comm.channel import get_channel, publish_channel, get_channels
|
from liteyuki.comm.channel import get_channel, publish_channel, get_channels
|
||||||
from liteyuki.comm.storage import shared_memory
|
from liteyuki.comm.storage import shared_memory
|
||||||
from liteyuki.comm.channel import channel_deliver_active_channel, channel_deliver_passive_channel
|
from liteyuki.comm.channel import (
|
||||||
|
channel_deliver_active_channel,
|
||||||
|
channel_deliver_passive_channel,
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
from liteyuki.comm import channel
|
from liteyuki.comm import channel
|
||||||
from liteyuki.comm import storage
|
from liteyuki.comm import storage
|
||||||
@@ -34,20 +40,18 @@ else:
|
|||||||
TARGET_FUNC: TypeAlias = Callable[..., Any]
|
TARGET_FUNC: TypeAlias = Callable[..., Any]
|
||||||
TIMEOUT = 10
|
TIMEOUT = 10
|
||||||
|
|
||||||
__all__ = [
|
__all__ = ["ProcessManager", "sub_process_manager"]
|
||||||
"ProcessManager"
|
|
||||||
]
|
|
||||||
multiprocessing.set_start_method("spawn", force=True)
|
multiprocessing.set_start_method("spawn", force=True)
|
||||||
|
|
||||||
|
|
||||||
class ChannelDeliver:
|
class ChannelDeliver:
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
active: Channel[Any],
|
active: Channel[Any],
|
||||||
passive: Channel[Any],
|
passive: Channel[Any],
|
||||||
channel_deliver_active: Channel[Channel[Any]],
|
channel_deliver_active: Channel[Channel[Any]],
|
||||||
channel_deliver_passive: Channel[tuple[str, dict]],
|
channel_deliver_passive: Channel[tuple[str, dict]],
|
||||||
publish: Channel[tuple[str, Any]],
|
publish: Channel[tuple[str, Any]],
|
||||||
):
|
):
|
||||||
self.active = active
|
self.active = active
|
||||||
self.passive = passive
|
self.passive = passive
|
||||||
@@ -57,7 +61,9 @@ class ChannelDeliver:
|
|||||||
|
|
||||||
|
|
||||||
# 函数处理一些跨进程通道的
|
# 函数处理一些跨进程通道的
|
||||||
def _delivery_channel_wrapper(func: TARGET_FUNC, cd: ChannelDeliver, sm: "KeyValueStore", *args, **kwargs):
|
def _delivery_channel_wrapper(
|
||||||
|
func: TARGET_FUNC, cd: ChannelDeliver, sm: "KeyValueStore", *args, **kwargs
|
||||||
|
):
|
||||||
"""
|
"""
|
||||||
子进程入口函数
|
子进程入口函数
|
||||||
处理一些操作
|
处理一些操作
|
||||||
@@ -68,8 +74,12 @@ def _delivery_channel_wrapper(func: TARGET_FUNC, cd: ChannelDeliver, sm: "KeyVal
|
|||||||
|
|
||||||
channel.active_channel = cd.active # 子进程主动通道
|
channel.active_channel = cd.active # 子进程主动通道
|
||||||
channel.passive_channel = cd.passive # 子进程被动通道
|
channel.passive_channel = cd.passive # 子进程被动通道
|
||||||
channel.channel_deliver_active_channel = cd.channel_deliver_active # 子进程通道传递主动通道
|
channel.channel_deliver_active_channel = (
|
||||||
channel.channel_deliver_passive_channel = cd.channel_deliver_passive # 子进程通道传递被动通道
|
cd.channel_deliver_active
|
||||||
|
) # 子进程通道传递主动通道
|
||||||
|
channel.channel_deliver_passive_channel = (
|
||||||
|
cd.channel_deliver_passive
|
||||||
|
) # 子进程通道传递被动通道
|
||||||
channel.publish_channel = cd.publish # 子进程发布通道
|
channel.publish_channel = cd.publish # 子进程发布通道
|
||||||
|
|
||||||
# 给子进程创建共享内存实例
|
# 给子进程创建共享内存实例
|
||||||
@@ -102,8 +112,12 @@ class ProcessManager:
|
|||||||
chan_active = get_channel(f"{name}-active")
|
chan_active = get_channel(f"{name}-active")
|
||||||
|
|
||||||
def _start_process():
|
def _start_process():
|
||||||
process = Process(target=self.targets[name][0], args=self.targets[name][1],
|
process = Process(
|
||||||
kwargs=self.targets[name][2], daemon=True)
|
target=self.targets[name][0],
|
||||||
|
args=self.targets[name][1],
|
||||||
|
kwargs=self.targets[name][2],
|
||||||
|
daemon=True,
|
||||||
|
)
|
||||||
self.processes[name] = process
|
self.processes[name] = process
|
||||||
process.start()
|
process.start()
|
||||||
|
|
||||||
@@ -133,7 +147,9 @@ class ProcessManager:
|
|||||||
|
|
||||||
for name in self.targets:
|
for name in self.targets:
|
||||||
logger.debug(f"Starting process {name}")
|
logger.debug(f"Starting process {name}")
|
||||||
threading.Thread(target=self._run_process, args=(name, ), daemon=True).start()
|
threading.Thread(
|
||||||
|
target=self._run_process, args=(name,), daemon=True
|
||||||
|
).start()
|
||||||
|
|
||||||
def add_target(self, name: str, target: TARGET_FUNC, args: tuple = (), kwargs=None):
|
def add_target(self, name: str, target: TARGET_FUNC, args: tuple = (), kwargs=None):
|
||||||
"""
|
"""
|
||||||
@@ -154,10 +170,14 @@ class ProcessManager:
|
|||||||
passive=chan_passive,
|
passive=chan_passive,
|
||||||
channel_deliver_active=channel_deliver_active_channel,
|
channel_deliver_active=channel_deliver_active_channel,
|
||||||
channel_deliver_passive=channel_deliver_passive_channel,
|
channel_deliver_passive=channel_deliver_passive_channel,
|
||||||
publish=publish_channel
|
publish=publish_channel,
|
||||||
)
|
)
|
||||||
|
|
||||||
self.targets[name] = (_delivery_channel_wrapper, (target, channel_deliver, shared_memory, *args), kwargs)
|
self.targets[name] = (
|
||||||
|
_delivery_channel_wrapper,
|
||||||
|
(target, channel_deliver, shared_memory, *args),
|
||||||
|
kwargs,
|
||||||
|
)
|
||||||
# 主进程通道
|
# 主进程通道
|
||||||
|
|
||||||
def join_all(self):
|
def join_all(self):
|
||||||
@@ -199,3 +219,54 @@ class ProcessManager:
|
|||||||
if name not in self.targets:
|
if name not in self.targets:
|
||||||
logger.warning(f"Process {name} not found.")
|
logger.warning(f"Process {name} not found.")
|
||||||
return self.processes[name].is_alive()
|
return self.processes[name].is_alive()
|
||||||
|
|
||||||
|
|
||||||
|
# new version
|
||||||
|
|
||||||
|
|
||||||
|
class _SubProcessManager:
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
self.processes: dict[str, SubProcess] = {}
|
||||||
|
|
||||||
|
def new_process(
|
||||||
|
self, name: str, *args, **kwargs
|
||||||
|
) -> Callable[[ProcessFuncType], None]:
|
||||||
|
def decorator(func: ProcessFuncType):
|
||||||
|
self.processes[name] = SubProcess(name, func, *args, **kwargs)
|
||||||
|
|
||||||
|
return decorator
|
||||||
|
|
||||||
|
def add(self, name: str, func: ProcessFuncType, *args, **kwargs):
|
||||||
|
"""
|
||||||
|
添加子进程
|
||||||
|
Args:
|
||||||
|
func: 子进程函数
|
||||||
|
name: 子进程名称
|
||||||
|
args: 子进程函数参数
|
||||||
|
kwargs: 子进程函数关键字参数
|
||||||
|
Returns:
|
||||||
|
"""
|
||||||
|
self.processes[name] = SubProcess(name, func, *args, **kwargs)
|
||||||
|
|
||||||
|
def start(self, name: str):
|
||||||
|
"""
|
||||||
|
启动指定子进程
|
||||||
|
Args:
|
||||||
|
name: 子进程名称
|
||||||
|
Returns:
|
||||||
|
"""
|
||||||
|
if name not in self.processes:
|
||||||
|
raise KeyError(f"Process {name} not found.")
|
||||||
|
self.processes[name].start()
|
||||||
|
|
||||||
|
def start_all(self):
|
||||||
|
"""
|
||||||
|
启动所有子进程
|
||||||
|
"""
|
||||||
|
for name, process in self.processes.items():
|
||||||
|
process.start()
|
||||||
|
logger.debug(f"Starting process {name}")
|
||||||
|
|
||||||
|
|
||||||
|
sub_process_manager = _SubProcessManager()
|
||||||
|
@@ -60,7 +60,6 @@ def load_plugin(module_path: str | Path) -> Optional[Plugin]:
|
|||||||
f"{metadata.name}({module.__name__.split('.')[-1]})", metadata.type
|
f"{metadata.name}({module.__name__.split('.')[-1]})", metadata.type
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
|
|
||||||
logger.opt(colors=True).warning(
|
logger.opt(colors=True).warning(
|
||||||
f'The metadata of Liteyuki plugin "{module.__name__}" is not specified, use empty.'
|
f'The metadata of Liteyuki plugin "{module.__name__}" is not specified, use empty.'
|
||||||
)
|
)
|
||||||
|
3
liteyuki_flow/__init__.py
Normal file
3
liteyuki_flow/__init__.py
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
"""
|
||||||
|
Module docs
|
||||||
|
"""
|
60
liteyuki_flow/__main__.py
Normal file
60
liteyuki_flow/__main__.py
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
"""
|
||||||
|
Module docs
|
||||||
|
"""
|
||||||
|
import os
|
||||||
|
from github import Github
|
||||||
|
from argparse import ArgumentParser
|
||||||
|
|
||||||
|
from liteyuki_flow.const import PLUGIN_PREFIX, RESOURCE_PREFIX
|
||||||
|
from liteyuki_flow.typ import err, nil # type: ignore
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
parser = ArgumentParser()
|
||||||
|
parser.add_argument("--handle", action="store_true") # 处理issue
|
||||||
|
|
||||||
|
parser.add_argument("-p", "--parse", action="store_true") # 解析markdown文件
|
||||||
|
parser.add_argument("-i", "--input", type=str, help="Path to the markdown file.")
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
if args.handle:
|
||||||
|
print("Starting the issue handler module...")
|
||||||
|
ISSUE_NUMBER = os.getenv("ISSUE_NUMBER")
|
||||||
|
REPOSITORY = os.getenv("REPOSITORY")
|
||||||
|
ACT_TYPE = os.getenv("ACT_TYPE") # opened, edited, closed, reopened
|
||||||
|
if ISSUE_NUMBER is None or REPOSITORY is None or ACT_TYPE is None:
|
||||||
|
raise ValueError("Issue number, repository and action type are required.")
|
||||||
|
|
||||||
|
g = Github(os.getenv("GITHUB_TOKEN"))
|
||||||
|
repo = g.get_repo(REPOSITORY)
|
||||||
|
issue = g.get_repo(REPOSITORY).get_issue(int(ISSUE_NUMBER))
|
||||||
|
|
||||||
|
# 审资源
|
||||||
|
if issue.title.strip().startswith(RESOURCE_PREFIX):
|
||||||
|
from liteyuki_flow.resource_handler import handle_resource # type: ignore
|
||||||
|
handle_resource(github=g, issue=issue, repo=repo, act_type=ACT_TYPE)
|
||||||
|
|
||||||
|
# 审插件
|
||||||
|
elif issue.title.strip().startswith(PLUGIN_PREFIX):
|
||||||
|
from liteyuki_flow.plugin_handler import handle_plugin # type: ignore
|
||||||
|
pass
|
||||||
|
|
||||||
|
else:
|
||||||
|
print("No handler found for the issue.")
|
||||||
|
|
||||||
|
elif args.parse:
|
||||||
|
print("Starting the markdown parser module...")
|
||||||
|
from liteyuki_flow.markdown_parser import MarkdownParser # type: ignore
|
||||||
|
|
||||||
|
if args.input is None:
|
||||||
|
raise ValueError("Input file is required.")
|
||||||
|
with open(args.input, "r", encoding="utf-8") as f:
|
||||||
|
content = f.read()
|
||||||
|
|
||||||
|
md_parser = MarkdownParser(content) # type: ignore
|
||||||
|
err = md_parser.parse_front_matters() # type: ignore
|
||||||
|
if err != nil:
|
||||||
|
print(f"Err: {err}")
|
||||||
|
for k, v in md_parser.front_matters.content.items():
|
||||||
|
print(f"{k}: {v}")
|
||||||
|
else:
|
||||||
|
print("No module specified.")
|
19
liteyuki_flow/const.py
Normal file
19
liteyuki_flow/const.py
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
"""
|
||||||
|
Module docs
|
||||||
|
"""
|
||||||
|
|
||||||
|
OPENED = "opened"
|
||||||
|
EDITED = "edited"
|
||||||
|
CLOSED = "closed"
|
||||||
|
REOPENED = "reopened"
|
||||||
|
RESOURCE_PREFIX = "Resource: "
|
||||||
|
PLUGIN_PREFIX = "Plugin: "
|
||||||
|
|
||||||
|
PLUGIN_JSON = "docs/public/plugins.json"
|
||||||
|
RESOURCE_JSON = "docs/public/resources.json"
|
||||||
|
|
||||||
|
edit_content_tip = "若要修改请编辑这段front matter,不要编辑正文/If you want to modify, please edit the front matter, do not edit the body"
|
||||||
|
|
||||||
|
edit_tip = "如需修改请直接编辑issue,请不要新建issue,我会自动检查"
|
||||||
|
|
||||||
|
bot_id = "liteyuki-flow"
|
146
liteyuki_flow/markdown_parser.py
Normal file
146
liteyuki_flow/markdown_parser.py
Normal file
@@ -0,0 +1,146 @@
|
|||||||
|
"""
|
||||||
|
从markdown提取插件/资源信息
|
||||||
|
"""
|
||||||
|
from typing import Any
|
||||||
|
|
||||||
|
from github.Issue import Issue
|
||||||
|
|
||||||
|
from liteyuki_flow.typ import Nil, err, nil # type: ignore
|
||||||
|
|
||||||
|
|
||||||
|
# # xxx
|
||||||
|
class Header:
|
||||||
|
def __init__(self, level: int, content: str):
|
||||||
|
self.level = level
|
||||||
|
self.content = content
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return f'Header({self.level}, {self.content})'
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return self.__str__()
|
||||||
|
|
||||||
|
|
||||||
|
# - xxx
|
||||||
|
class List:
|
||||||
|
def __init__(self, level: int, content: str):
|
||||||
|
self.level = level
|
||||||
|
self.content = content
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return f'List({self.level}, {self.content})'
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return self.__str__()
|
||||||
|
|
||||||
|
|
||||||
|
class FrontMatter:
|
||||||
|
def __init__(self, content: dict[str, str]):
|
||||||
|
self.content = content
|
||||||
|
|
||||||
|
def __setitem__(self, key: str, value: str):
|
||||||
|
self.content[key] = value
|
||||||
|
|
||||||
|
def get(self, key, default=None) -> Any:
|
||||||
|
return self.content.get(key, default)
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return "\n".join([f'{k}: {v}' for k, v in self.content.items()])
|
||||||
|
|
||||||
|
|
||||||
|
class MarkdownParser:
|
||||||
|
def __init__(self, content: str):
|
||||||
|
self.content = content
|
||||||
|
self.content_lines = content.split('\n')
|
||||||
|
self.front_matters: FrontMatter = FrontMatter({})
|
||||||
|
|
||||||
|
self._content_list: list[Any] = [self.front_matters]
|
||||||
|
|
||||||
|
self.lineno = 0
|
||||||
|
|
||||||
|
self._parsed = False
|
||||||
|
|
||||||
|
def parse_front_matters(self) -> err:
|
||||||
|
if self.content_lines[self.lineno].strip() != '---':
|
||||||
|
return ValueError('Invalid front matter')
|
||||||
|
while self.lineno < len(self.content_lines):
|
||||||
|
self._next_line()
|
||||||
|
line = self.content_lines[self.lineno]
|
||||||
|
if line.strip() == '---':
|
||||||
|
break
|
||||||
|
if line.strip().startswith('#'):
|
||||||
|
# fm注释
|
||||||
|
continue
|
||||||
|
try:
|
||||||
|
key, value = line.split(':', 1)
|
||||||
|
except ValueError:
|
||||||
|
return Exception(f'Invalid front matter: {line}')
|
||||||
|
self.front_matters[key.strip()] = value.strip()
|
||||||
|
return nil
|
||||||
|
|
||||||
|
def build_front_matters(self) -> str:
|
||||||
|
return "---\n" + str(self.front_matters) + "\n---"
|
||||||
|
|
||||||
|
def _parse_content(self) -> tuple[list[Any], err]:
|
||||||
|
content: list[Any] = []
|
||||||
|
while self.lineno < len(self.content_lines):
|
||||||
|
item, e = self._parse_line()
|
||||||
|
if e != nil:
|
||||||
|
return nil, e
|
||||||
|
content.append(item)
|
||||||
|
return content, nil
|
||||||
|
|
||||||
|
def _parse_line(self) -> tuple[Any, err]:
|
||||||
|
line = self.content_lines[self.lineno]
|
||||||
|
if line.startswith('#'):
|
||||||
|
# 计算start有几个#
|
||||||
|
start = 0
|
||||||
|
while line[start] == '#':
|
||||||
|
start += 1
|
||||||
|
return Header(start, line[start:].strip()), nil
|
||||||
|
elif line.startswith('-'):
|
||||||
|
start = 0
|
||||||
|
while line[start] == '-':
|
||||||
|
start += 1
|
||||||
|
return List(start, line[start:].strip()), nil
|
||||||
|
|
||||||
|
# 处理<!--注释 continue
|
||||||
|
elif line.strip().startswith('<!--'):
|
||||||
|
while not line.strip().endswith('-->'):
|
||||||
|
self._next_line()
|
||||||
|
line = self.content_lines[self.lineno]
|
||||||
|
return None, nil
|
||||||
|
# 处理[//]: # (注释) continue
|
||||||
|
elif line.strip().startswith('[//]: #'):
|
||||||
|
self._next_line()
|
||||||
|
return None, nil
|
||||||
|
|
||||||
|
self._next_line()
|
||||||
|
return nil, ValueError(f'Invalid line: {line}')
|
||||||
|
|
||||||
|
def _next_line(self):
|
||||||
|
self.lineno += 1
|
||||||
|
|
||||||
|
def parse(self) -> tuple[list[Any] | Nil, err]:
|
||||||
|
if self._parsed:
|
||||||
|
return self._content_list, nil
|
||||||
|
|
||||||
|
e = self.parse_front_matters()
|
||||||
|
if e != nil:
|
||||||
|
return nil, e
|
||||||
|
|
||||||
|
ls, e = self._parse_content()
|
||||||
|
if e != nil:
|
||||||
|
return nil, e
|
||||||
|
|
||||||
|
self._content_list.extend(ls)
|
||||||
|
self._parsed = True
|
||||||
|
|
||||||
|
return self._content_list, nil
|
||||||
|
|
||||||
|
|
||||||
|
# 解析资源发布issue体
|
||||||
|
def parse_resource_publish_info(issue: Issue) -> dict[str, str]:
|
||||||
|
parser = MarkdownParser(issue.body)
|
||||||
|
parser.parse_front_matters()
|
||||||
|
return parser.front_matters
|
7
liteyuki_flow/plugin_handler.py
Normal file
7
liteyuki_flow/plugin_handler.py
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
"""
|
||||||
|
Module docs
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
def plugin_handler():
|
||||||
|
pass
|
3
liteyuki_flow/requirements.txt
Normal file
3
liteyuki_flow/requirements.txt
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
PyGithub==2.4.0
|
||||||
|
requests==2.31.0
|
||||||
|
pyyaml==6.0.2
|
199
liteyuki_flow/resource_handler.py
Normal file
199
liteyuki_flow/resource_handler.py
Normal file
@@ -0,0 +1,199 @@
|
|||||||
|
"""
|
||||||
|
Module docs
|
||||||
|
"""
|
||||||
|
import requests # type: ignore
|
||||||
|
import zipfile
|
||||||
|
|
||||||
|
from github import Github, InputGitTreeElement, GitTree
|
||||||
|
from github.Issue import Issue
|
||||||
|
from github.Repository import Repository
|
||||||
|
import json
|
||||||
|
import yaml
|
||||||
|
|
||||||
|
from liteyuki_flow.const import OPENED, EDITED, CLOSED, REOPENED, RESOURCE_JSON, bot_id, edit_tip
|
||||||
|
from liteyuki_flow.markdown_parser import MarkdownParser
|
||||||
|
from liteyuki_flow.typ import err, nil
|
||||||
|
|
||||||
|
user_agent = "liteyuki-flow"
|
||||||
|
|
||||||
|
headers = {
|
||||||
|
"User-Agent": user_agent
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def push_check_result(issue: Issue, result: str):
|
||||||
|
cid = None
|
||||||
|
for cm in issue.get_comments():
|
||||||
|
if cm.body.startswith("检查结果") and cm.user.login == bot_id:
|
||||||
|
cid = cm.id
|
||||||
|
break
|
||||||
|
if cid is not None:
|
||||||
|
issue.get_comment(cid).edit("检查结果: " + result)
|
||||||
|
else:
|
||||||
|
issue.create_comment("检查结果: " + result)
|
||||||
|
|
||||||
|
|
||||||
|
def push_publish_result(issue: Issue, result: str):
|
||||||
|
cid = None
|
||||||
|
for cm in issue.get_comments():
|
||||||
|
if cm.body.startswith("发布结果") and cm.user.login == bot_id:
|
||||||
|
cid = cm.id
|
||||||
|
break
|
||||||
|
if cid is not None:
|
||||||
|
issue.get_comment(cid).edit("发布结果: " + result)
|
||||||
|
else:
|
||||||
|
issue.create_comment("发布结果: " + result)
|
||||||
|
|
||||||
|
|
||||||
|
# opened: 创建新的资源包,预审核
|
||||||
|
# edited: 编辑资源包信息,需重新审核
|
||||||
|
# closed: 审核通过,修改json并提交
|
||||||
|
# reopened: 重新打开,无操作
|
||||||
|
def on_first_open(github: Github, issue: Issue, repo: Repository):
|
||||||
|
issue.create_comment("已收到资源包发布请求,我会马上开始预检. " + edit_tip)
|
||||||
|
push_check_result(issue, "请等待")
|
||||||
|
issue.add_to_labels("Resource")
|
||||||
|
|
||||||
|
|
||||||
|
# opened | edited
|
||||||
|
def pre_check(github: Github, issue: Issue, repo: Repository) -> err:
|
||||||
|
parser = MarkdownParser(issue.body)
|
||||||
|
parser.parse_front_matters()
|
||||||
|
name = parser.front_matters.get("name")
|
||||||
|
desc = parser.front_matters.get("desc")
|
||||||
|
link = parser.front_matters.get("link")
|
||||||
|
homepage = parser.front_matters.get("homepage") # optional
|
||||||
|
author = parser.front_matters.get("author")
|
||||||
|
|
||||||
|
if not all((name, desc, link, author)):
|
||||||
|
push_check_result(issue, "❌ name, desc, link, homepage 及 author 为必填字段.")
|
||||||
|
return ValueError("name, desc, link, homepage 及 author 为必填字段.")
|
||||||
|
|
||||||
|
# 下载并解析资源包
|
||||||
|
r = requests.get(link, headers=headers)
|
||||||
|
if r.status_code != 200:
|
||||||
|
push_check_result(issue, "❌ 下载失败.")
|
||||||
|
return ValueError("下载失败.")
|
||||||
|
try:
|
||||||
|
with open(f"{name}.zip", "wb") as f:
|
||||||
|
f.write(r.content)
|
||||||
|
# 解压
|
||||||
|
with zipfile.ZipFile(f"{name}.zip", "r") as z:
|
||||||
|
z.extractall(f"{name}")
|
||||||
|
# 检测包内metadata.yml文件
|
||||||
|
data = yaml.load(open(f"{name}/metadata.yml"), Loader=yaml.SafeLoader)
|
||||||
|
except Exception as e:
|
||||||
|
push_check_result(issue, "❌ 解析资源包失败,可能是格式问题或metadata.yml不存在: " + str(e))
|
||||||
|
return e
|
||||||
|
|
||||||
|
# 检测必要字段 name,description,version
|
||||||
|
if not all((data.get("name"), data.get("description"), data.get("version"))):
|
||||||
|
push_check_result(issue, "❌ 元数据中缺少必要字段 name, description 或 version.")
|
||||||
|
return ValueError("元数据中缺少必要字段 name, description 或 version.")
|
||||||
|
|
||||||
|
# 不检测重复资源包,因为资源包可能有多个版本
|
||||||
|
# 检测通过,编辑原issue
|
||||||
|
metadata_markdown = f"**名称**: {data.get('name')}\n**描述**: {data.get('description')}\n**版本**: {data.get('version')}\n"
|
||||||
|
for k, v in data.items():
|
||||||
|
if k not in ("name", "description", "version"):
|
||||||
|
metadata_markdown += f"**{k}**: {v}\n"
|
||||||
|
|
||||||
|
new_issue_body = f"---\nname: {name}\ndesc: {desc}\nlink: {link}\nhomepage: {homepage}\nauthor: {author}\n---\n"
|
||||||
|
|
||||||
|
publish_info = f"## 发布信息\n"
|
||||||
|
publish_info += f"**名称**: {name}\n"
|
||||||
|
publish_info += f"**描述**: {desc}\n"
|
||||||
|
publish_info += f"**作者**: {author}\n"
|
||||||
|
publish_info += f"**主页**: {homepage}\n"
|
||||||
|
publish_info += f"**下载**: {link}\n"
|
||||||
|
# 遍历其他字段
|
||||||
|
for k, v in data.items():
|
||||||
|
if k not in ("name", "description", "version"):
|
||||||
|
new_issue_body += f"**{k}**: {v}\n"
|
||||||
|
|
||||||
|
issue.edit(title=f"Resource: {name}")
|
||||||
|
issue.add_to_labels("pre-checked")
|
||||||
|
push_check_result(issue, f"✅ 预检查通过,等待管理员人工审核\n{publish_info}\n## 元数据\n{metadata_markdown}")
|
||||||
|
return nil
|
||||||
|
|
||||||
|
|
||||||
|
# closed
|
||||||
|
def add_resource(github: Github, issue: Issue, repo: Repository) -> err:
|
||||||
|
# 检测关闭时是否有管理员发布的通过评论
|
||||||
|
try:
|
||||||
|
if "pre-checked" not in [l.name for l in issue.labels]:
|
||||||
|
issue.edit(state="open")
|
||||||
|
push_publish_result(issue, "❌ 请先通过预检查。")
|
||||||
|
return ValueError("请先进行预检查。")
|
||||||
|
|
||||||
|
# 检测评论
|
||||||
|
for cm in issue.get_comments():
|
||||||
|
if cm.body.startswith(("通过", "pass",)):
|
||||||
|
# 检测用户是否是管理员
|
||||||
|
if cm.user.login not in [u.login for u in repo.get_collaborators()]:
|
||||||
|
issue.edit(state="open")
|
||||||
|
push_publish_result(issue, "❌ 你不是仓库管理员,无法发布资源包。")
|
||||||
|
return ValueError("你不是仓库管理员,无法发布资源包。")
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
issue.edit(state="open")
|
||||||
|
push_publish_result(issue, "❌ 管理员未审核。")
|
||||||
|
return ValueError("管理员未审核。")
|
||||||
|
|
||||||
|
parser = MarkdownParser(issue.body)
|
||||||
|
parser.parse_front_matters()
|
||||||
|
name = parser.front_matters.get("name")
|
||||||
|
desc = parser.front_matters.get("desc")
|
||||||
|
link = parser.front_matters.get("link")
|
||||||
|
homepage = parser.front_matters.get("homepage") # optional
|
||||||
|
author = parser.front_matters.get("author")
|
||||||
|
|
||||||
|
# 编辑仓库内的json文件
|
||||||
|
resources = json.load(open(RESOURCE_JSON))
|
||||||
|
resources.append({
|
||||||
|
"name": name,
|
||||||
|
"description": desc,
|
||||||
|
"link": link,
|
||||||
|
"homepage": homepage,
|
||||||
|
"author": author
|
||||||
|
})
|
||||||
|
ref = repo.get_git_ref("heads/main")
|
||||||
|
tree = repo.create_git_tree(
|
||||||
|
base_tree=repo.get_git_commit(ref.object.sha).tree,
|
||||||
|
tree=[
|
||||||
|
InputGitTreeElement(
|
||||||
|
path=RESOURCE_JSON,
|
||||||
|
mode="100644",
|
||||||
|
type="blob",
|
||||||
|
content=json.dumps(resources, indent=4, ensure_ascii=False)
|
||||||
|
)
|
||||||
|
]
|
||||||
|
)
|
||||||
|
commit = repo.create_git_commit(
|
||||||
|
message=f":package: 发布资源: {name}",
|
||||||
|
tree=tree,
|
||||||
|
parents=[repo.get_git_commit(ref.object.sha)]
|
||||||
|
)
|
||||||
|
ref.edit(commit.sha)
|
||||||
|
if "pre-checked" in [l.name for l in issue.labels]:
|
||||||
|
issue.remove_from_labels("pre-checked")
|
||||||
|
issue.add_to_labels("published")
|
||||||
|
push_publish_result(issue, f"✅ 资源包 {name} 已发布!商店页面稍后就会更新。")
|
||||||
|
return nil
|
||||||
|
except Exception as e:
|
||||||
|
issue.edit(state="open")
|
||||||
|
push_publish_result(issue, f"❌ 发布失败: {str(e)}")
|
||||||
|
return e
|
||||||
|
|
||||||
|
|
||||||
|
def handle_resource(github: Github, issue: Issue, repo: Repository, act_type: str):
|
||||||
|
if act_type in (OPENED, EDITED):
|
||||||
|
if act_type == OPENED:
|
||||||
|
on_first_open(github, issue, repo)
|
||||||
|
pre_check(github, issue, repo)
|
||||||
|
elif act_type == CLOSED:
|
||||||
|
e = add_resource(github, issue, repo)
|
||||||
|
if e != nil:
|
||||||
|
print(f"Error: {e}")
|
||||||
|
else:
|
||||||
|
print("No operation found for the issue: ", act_type)
|
26
liteyuki_flow/ts.md
Normal file
26
liteyuki_flow/ts.md
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
---
|
||||||
|
# 请修改此处内容/Please modify the content here
|
||||||
|
# 不要修改正文中的内容/Do not modify the content in the body
|
||||||
|
name: PluginName
|
||||||
|
desc: 插件描述
|
||||||
|
author: 作者名
|
||||||
|
link: 下载链接
|
||||||
|
homepage: 主页链接
|
||||||
|
---
|
||||||
|
<!-- 以下字段自动生成,请勿编辑 -->
|
||||||
|
# Plugin: PluginName
|
||||||
|
|
||||||
|
## 插件信息
|
||||||
|
|
||||||
|
- **包名**: PluginName
|
||||||
|
- **描述**: 插件描述
|
||||||
|
- **作者**: AuthorName
|
||||||
|
- **主页**: https://a.b.c
|
||||||
|
|
||||||
|
## 资源包信息
|
||||||
|
|
||||||
|
- **名称**: PluginName
|
||||||
|
- **描述**: 插件描述
|
||||||
|
- **作者**: AuthorName
|
||||||
|
- **主页**: https://a.b.c
|
||||||
|
- **下载**: https://a.b.c
|
20
liteyuki_flow/typ.py
Normal file
20
liteyuki_flow/typ.py
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
"""
|
||||||
|
Module docs
|
||||||
|
"""
|
||||||
|
from typing import TypeAlias
|
||||||
|
|
||||||
|
|
||||||
|
class Nil():
|
||||||
|
def __eq__(self, other):
|
||||||
|
if isinstance(other, Nil):
|
||||||
|
return True
|
||||||
|
return other is None
|
||||||
|
|
||||||
|
# 不等于
|
||||||
|
def __ne__(self, other):
|
||||||
|
return not self.__eq__(other)
|
||||||
|
|
||||||
|
|
||||||
|
nil = Nil()
|
||||||
|
|
||||||
|
err: TypeAlias = Exception | Nil
|
510
pdm.lock
generated
Normal file
510
pdm.lock
generated
Normal file
@@ -0,0 +1,510 @@
|
|||||||
|
# This file is @generated by PDM.
|
||||||
|
# It is not intended for manual editing.
|
||||||
|
|
||||||
|
[metadata]
|
||||||
|
groups = ["default", "dev"]
|
||||||
|
strategy = ["inherit_metadata"]
|
||||||
|
lock_version = "4.5.0"
|
||||||
|
content_hash = "sha256:ca1b7f108fb7c5bc51977cf165511cbc7a95f64bc4effd6b6597f60bf893ba77"
|
||||||
|
|
||||||
|
[[metadata.targets]]
|
||||||
|
requires_python = ">=3.10"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "annotated-types"
|
||||||
|
version = "0.7.0"
|
||||||
|
requires_python = ">=3.8"
|
||||||
|
summary = "Reusable constraint types to use with typing.Annotated"
|
||||||
|
groups = ["default"]
|
||||||
|
dependencies = [
|
||||||
|
"typing-extensions>=4.0.0; python_version < \"3.9\"",
|
||||||
|
]
|
||||||
|
files = [
|
||||||
|
{file = "annotated_types-0.7.0-py3-none-any.whl", hash = "sha256:1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53"},
|
||||||
|
{file = "annotated_types-0.7.0.tar.gz", hash = "sha256:aff07c09a53a08bc8cfccb9c85b05f1aa9a2a6f23728d790723543408344ce89"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "black"
|
||||||
|
version = "24.10.0"
|
||||||
|
requires_python = ">=3.9"
|
||||||
|
summary = "The uncompromising code formatter."
|
||||||
|
groups = ["dev"]
|
||||||
|
dependencies = [
|
||||||
|
"click>=8.0.0",
|
||||||
|
"mypy-extensions>=0.4.3",
|
||||||
|
"packaging>=22.0",
|
||||||
|
"pathspec>=0.9.0",
|
||||||
|
"platformdirs>=2",
|
||||||
|
"tomli>=1.1.0; python_version < \"3.11\"",
|
||||||
|
"typing-extensions>=4.0.1; python_version < \"3.11\"",
|
||||||
|
]
|
||||||
|
files = [
|
||||||
|
{file = "black-24.10.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e6668650ea4b685440857138e5fe40cde4d652633b1bdffc62933d0db4ed9812"},
|
||||||
|
{file = "black-24.10.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:1c536fcf674217e87b8cc3657b81809d3c085d7bf3ef262ead700da345bfa6ea"},
|
||||||
|
{file = "black-24.10.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:649fff99a20bd06c6f727d2a27f401331dc0cc861fb69cde910fe95b01b5928f"},
|
||||||
|
{file = "black-24.10.0-cp310-cp310-win_amd64.whl", hash = "sha256:fe4d6476887de70546212c99ac9bd803d90b42fc4767f058a0baa895013fbb3e"},
|
||||||
|
{file = "black-24.10.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:5a2221696a8224e335c28816a9d331a6c2ae15a2ee34ec857dcf3e45dbfa99ad"},
|
||||||
|
{file = "black-24.10.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f9da3333530dbcecc1be13e69c250ed8dfa67f43c4005fb537bb426e19200d50"},
|
||||||
|
{file = "black-24.10.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4007b1393d902b48b36958a216c20c4482f601569d19ed1df294a496eb366392"},
|
||||||
|
{file = "black-24.10.0-cp311-cp311-win_amd64.whl", hash = "sha256:394d4ddc64782e51153eadcaaca95144ac4c35e27ef9b0a42e121ae7e57a9175"},
|
||||||
|
{file = "black-24.10.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:b5e39e0fae001df40f95bd8cc36b9165c5e2ea88900167bddf258bacef9bbdc3"},
|
||||||
|
{file = "black-24.10.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:d37d422772111794b26757c5b55a3eade028aa3fde43121ab7b673d050949d65"},
|
||||||
|
{file = "black-24.10.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:14b3502784f09ce2443830e3133dacf2c0110d45191ed470ecb04d0f5f6fcb0f"},
|
||||||
|
{file = "black-24.10.0-cp312-cp312-win_amd64.whl", hash = "sha256:30d2c30dc5139211dda799758559d1b049f7f14c580c409d6ad925b74a4208a8"},
|
||||||
|
{file = "black-24.10.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:1cbacacb19e922a1d75ef2b6ccaefcd6e93a2c05ede32f06a21386a04cedb981"},
|
||||||
|
{file = "black-24.10.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:1f93102e0c5bb3907451063e08b9876dbeac810e7da5a8bfb7aeb5a9ef89066b"},
|
||||||
|
{file = "black-24.10.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ddacb691cdcdf77b96f549cf9591701d8db36b2f19519373d60d31746068dbf2"},
|
||||||
|
{file = "black-24.10.0-cp313-cp313-win_amd64.whl", hash = "sha256:680359d932801c76d2e9c9068d05c6b107f2584b2a5b88831c83962eb9984c1b"},
|
||||||
|
{file = "black-24.10.0-py3-none-any.whl", hash = "sha256:3bb2b7a1f7b685f85b11fed1ef10f8a9148bceb49853e47a294a3dd963c1dd7d"},
|
||||||
|
{file = "black-24.10.0.tar.gz", hash = "sha256:846ea64c97afe3bc677b761787993be4991810ecc7a4a937816dd6bddedc4875"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "click"
|
||||||
|
version = "8.1.7"
|
||||||
|
requires_python = ">=3.7"
|
||||||
|
summary = "Composable command line interface toolkit"
|
||||||
|
groups = ["dev"]
|
||||||
|
dependencies = [
|
||||||
|
"colorama; platform_system == \"Windows\"",
|
||||||
|
"importlib-metadata; python_version < \"3.8\"",
|
||||||
|
]
|
||||||
|
files = [
|
||||||
|
{file = "click-8.1.7-py3-none-any.whl", hash = "sha256:ae74fb96c20a0277a1d615f1e4d73c8414f5a98db8b799a7931d1582f3390c28"},
|
||||||
|
{file = "click-8.1.7.tar.gz", hash = "sha256:ca9853ad459e787e2192211578cc907e7594e294c7ccc834310722b41b9ca6de"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "colorama"
|
||||||
|
version = "0.4.6"
|
||||||
|
requires_python = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7"
|
||||||
|
summary = "Cross-platform colored terminal text."
|
||||||
|
groups = ["default", "dev"]
|
||||||
|
marker = "sys_platform == \"win32\" or platform_system == \"Windows\""
|
||||||
|
files = [
|
||||||
|
{file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"},
|
||||||
|
{file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "croterline"
|
||||||
|
version = "1.0.3"
|
||||||
|
requires_python = ">=3.10"
|
||||||
|
summary = "Default template for PDM package"
|
||||||
|
groups = ["default"]
|
||||||
|
dependencies = [
|
||||||
|
"magicoca>=1.0.1",
|
||||||
|
]
|
||||||
|
files = [
|
||||||
|
{file = "croterline-1.0.3-py3-none-any.whl", hash = "sha256:e934041248bba97382cc522c658d6c4f507dbcfe751e90a1d4cb3076b530e99b"},
|
||||||
|
{file = "croterline-1.0.3.tar.gz", hash = "sha256:eb3874a96ed06d98fe210731ad9352a854df81218fb2c25e707e2b641b6daffb"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "exceptiongroup"
|
||||||
|
version = "1.2.2"
|
||||||
|
requires_python = ">=3.7"
|
||||||
|
summary = "Backport of PEP 654 (exception groups)"
|
||||||
|
groups = ["dev"]
|
||||||
|
marker = "python_version < \"3.11\""
|
||||||
|
files = [
|
||||||
|
{file = "exceptiongroup-1.2.2-py3-none-any.whl", hash = "sha256:3111b9d131c238bec2f8f516e123e14ba243563fb135d3fe885990585aa7795b"},
|
||||||
|
{file = "exceptiongroup-1.2.2.tar.gz", hash = "sha256:47c2edf7c6738fafb49fd34290706d1a1a2f4d1c6df275526b62cbb4aa5393cc"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "iniconfig"
|
||||||
|
version = "2.0.0"
|
||||||
|
requires_python = ">=3.7"
|
||||||
|
summary = "brain-dead simple config-ini parsing"
|
||||||
|
groups = ["dev"]
|
||||||
|
files = [
|
||||||
|
{file = "iniconfig-2.0.0-py3-none-any.whl", hash = "sha256:b6a85871a79d2e3b22d2d1b94ac2824226a63c6b741c88f7ae975f18b6778374"},
|
||||||
|
{file = "iniconfig-2.0.0.tar.gz", hash = "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "loguru"
|
||||||
|
version = "0.7.2"
|
||||||
|
requires_python = ">=3.5"
|
||||||
|
summary = "Python logging made (stupidly) simple"
|
||||||
|
groups = ["default"]
|
||||||
|
dependencies = [
|
||||||
|
"aiocontextvars>=0.2.0; python_version < \"3.7\"",
|
||||||
|
"colorama>=0.3.4; sys_platform == \"win32\"",
|
||||||
|
"win32-setctime>=1.0.0; sys_platform == \"win32\"",
|
||||||
|
]
|
||||||
|
files = [
|
||||||
|
{file = "loguru-0.7.2-py3-none-any.whl", hash = "sha256:003d71e3d3ed35f0f8984898359d65b79e5b21943f78af86aa5491210429b8eb"},
|
||||||
|
{file = "loguru-0.7.2.tar.gz", hash = "sha256:e671a53522515f34fd406340ee968cb9ecafbc4b36c679da03c18fd8d0bd51ac"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "magicoca"
|
||||||
|
version = "1.0.1"
|
||||||
|
requires_python = ">=3.10"
|
||||||
|
summary = "A communication library for Python"
|
||||||
|
groups = ["default"]
|
||||||
|
files = [
|
||||||
|
{file = "magicoca-1.0.1-py3-none-any.whl", hash = "sha256:69e04be77f9c02d3d0730dc4e739246f4bdefee8b78631040b464cd98cdde51c"},
|
||||||
|
{file = "magicoca-1.0.1.tar.gz", hash = "sha256:0dbc9a35609db92ec79076f7126566c1e71bd4b853909ecbad9221dcc7fd6f31"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "mypy"
|
||||||
|
version = "1.11.2"
|
||||||
|
requires_python = ">=3.8"
|
||||||
|
summary = "Optional static typing for Python"
|
||||||
|
groups = ["dev"]
|
||||||
|
dependencies = [
|
||||||
|
"mypy-extensions>=1.0.0",
|
||||||
|
"tomli>=1.1.0; python_version < \"3.11\"",
|
||||||
|
"typing-extensions>=4.6.0",
|
||||||
|
]
|
||||||
|
files = [
|
||||||
|
{file = "mypy-1.11.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d42a6dd818ffce7be66cce644f1dff482f1d97c53ca70908dff0b9ddc120b77a"},
|
||||||
|
{file = "mypy-1.11.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:801780c56d1cdb896eacd5619a83e427ce436d86a3bdf9112527f24a66618fef"},
|
||||||
|
{file = "mypy-1.11.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:41ea707d036a5307ac674ea172875f40c9d55c5394f888b168033177fce47383"},
|
||||||
|
{file = "mypy-1.11.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:6e658bd2d20565ea86da7d91331b0eed6d2eee22dc031579e6297f3e12c758c8"},
|
||||||
|
{file = "mypy-1.11.2-cp310-cp310-win_amd64.whl", hash = "sha256:478db5f5036817fe45adb7332d927daa62417159d49783041338921dcf646fc7"},
|
||||||
|
{file = "mypy-1.11.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:75746e06d5fa1e91bfd5432448d00d34593b52e7e91a187d981d08d1f33d4385"},
|
||||||
|
{file = "mypy-1.11.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:a976775ab2256aadc6add633d44f100a2517d2388906ec4f13231fafbb0eccca"},
|
||||||
|
{file = "mypy-1.11.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:cd953f221ac1379050a8a646585a29574488974f79d8082cedef62744f0a0104"},
|
||||||
|
{file = "mypy-1.11.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:57555a7715c0a34421013144a33d280e73c08df70f3a18a552938587ce9274f4"},
|
||||||
|
{file = "mypy-1.11.2-cp311-cp311-win_amd64.whl", hash = "sha256:36383a4fcbad95f2657642a07ba22ff797de26277158f1cc7bd234821468b1b6"},
|
||||||
|
{file = "mypy-1.11.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:e8960dbbbf36906c5c0b7f4fbf2f0c7ffb20f4898e6a879fcf56a41a08b0d318"},
|
||||||
|
{file = "mypy-1.11.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:06d26c277962f3fb50e13044674aa10553981ae514288cb7d0a738f495550b36"},
|
||||||
|
{file = "mypy-1.11.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6e7184632d89d677973a14d00ae4d03214c8bc301ceefcdaf5c474866814c987"},
|
||||||
|
{file = "mypy-1.11.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:3a66169b92452f72117e2da3a576087025449018afc2d8e9bfe5ffab865709ca"},
|
||||||
|
{file = "mypy-1.11.2-cp312-cp312-win_amd64.whl", hash = "sha256:969ea3ef09617aff826885a22ece0ddef69d95852cdad2f60c8bb06bf1f71f70"},
|
||||||
|
{file = "mypy-1.11.2-py3-none-any.whl", hash = "sha256:b499bc07dbdcd3de92b0a8b29fdf592c111276f6a12fe29c30f6c417dd546d12"},
|
||||||
|
{file = "mypy-1.11.2.tar.gz", hash = "sha256:7f9993ad3e0ffdc95c2a14b66dee63729f021968bff8ad911867579c65d13a79"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "mypy-extensions"
|
||||||
|
version = "1.0.0"
|
||||||
|
requires_python = ">=3.5"
|
||||||
|
summary = "Type system extensions for programs checked with the mypy type checker."
|
||||||
|
groups = ["dev"]
|
||||||
|
files = [
|
||||||
|
{file = "mypy_extensions-1.0.0-py3-none-any.whl", hash = "sha256:4392f6c0eb8a5668a69e23d168ffa70f0be9ccfd32b5cc2d26a34ae5b844552d"},
|
||||||
|
{file = "mypy_extensions-1.0.0.tar.gz", hash = "sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "packaging"
|
||||||
|
version = "24.1"
|
||||||
|
requires_python = ">=3.8"
|
||||||
|
summary = "Core utilities for Python packages"
|
||||||
|
groups = ["dev"]
|
||||||
|
files = [
|
||||||
|
{file = "packaging-24.1-py3-none-any.whl", hash = "sha256:5b8f2217dbdbd2f7f384c41c628544e6d52f2d0f53c6d0c3ea61aa5d1d7ff124"},
|
||||||
|
{file = "packaging-24.1.tar.gz", hash = "sha256:026ed72c8ed3fcce5bf8950572258698927fd1dbda10a5e981cdf0ac37f4f002"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pathspec"
|
||||||
|
version = "0.12.1"
|
||||||
|
requires_python = ">=3.8"
|
||||||
|
summary = "Utility library for gitignore style pattern matching of file paths."
|
||||||
|
groups = ["dev"]
|
||||||
|
files = [
|
||||||
|
{file = "pathspec-0.12.1-py3-none-any.whl", hash = "sha256:a0d503e138a4c123b27490a4f7beda6a01c6f288df0e4a8b79c7eb0dc7b4cc08"},
|
||||||
|
{file = "pathspec-0.12.1.tar.gz", hash = "sha256:a482d51503a1ab33b1c67a6c3813a26953dbdc71c31dacaef9a838c4e29f5712"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pdm-backend"
|
||||||
|
version = "2.4.2"
|
||||||
|
requires_python = ">=3.8"
|
||||||
|
summary = "The build backend used by PDM that supports latest packaging standards"
|
||||||
|
groups = ["default"]
|
||||||
|
dependencies = [
|
||||||
|
"importlib-metadata>=3.6; python_version < \"3.10\"",
|
||||||
|
]
|
||||||
|
files = [
|
||||||
|
{file = "pdm_backend-2.4.2-py3-none-any.whl", hash = "sha256:8537a3273b19d6448eb07a4a1a92dedc0b60935344a037729ada7be33b5f71ad"},
|
||||||
|
{file = "pdm_backend-2.4.2.tar.gz", hash = "sha256:1f833e527ae172f34b4b84e2fcf1f65859a2a5ca746e496d8313b3ea6539969f"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "platformdirs"
|
||||||
|
version = "4.3.6"
|
||||||
|
requires_python = ">=3.8"
|
||||||
|
summary = "A small Python package for determining appropriate platform-specific dirs, e.g. a `user data dir`."
|
||||||
|
groups = ["dev"]
|
||||||
|
files = [
|
||||||
|
{file = "platformdirs-4.3.6-py3-none-any.whl", hash = "sha256:73e575e1408ab8103900836b97580d5307456908a03e92031bab39e4554cc3fb"},
|
||||||
|
{file = "platformdirs-4.3.6.tar.gz", hash = "sha256:357fb2acbc885b0419afd3ce3ed34564c13c9b95c89360cd9563f73aa5e2b907"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pluggy"
|
||||||
|
version = "1.5.0"
|
||||||
|
requires_python = ">=3.8"
|
||||||
|
summary = "plugin and hook calling mechanisms for python"
|
||||||
|
groups = ["dev"]
|
||||||
|
files = [
|
||||||
|
{file = "pluggy-1.5.0-py3-none-any.whl", hash = "sha256:44e1ad92c8ca002de6377e165f3e0f1be63266ab4d554740532335b9d75ea669"},
|
||||||
|
{file = "pluggy-1.5.0.tar.gz", hash = "sha256:2cffa88e94fdc978c4c574f15f9e59b7f4201d439195c3715ca9e2486f1d0cf1"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pydantic"
|
||||||
|
version = "2.9.2"
|
||||||
|
requires_python = ">=3.8"
|
||||||
|
summary = "Data validation using Python type hints"
|
||||||
|
groups = ["default"]
|
||||||
|
dependencies = [
|
||||||
|
"annotated-types>=0.6.0",
|
||||||
|
"pydantic-core==2.23.4",
|
||||||
|
"typing-extensions>=4.12.2; python_version >= \"3.13\"",
|
||||||
|
"typing-extensions>=4.6.1; python_version < \"3.13\"",
|
||||||
|
]
|
||||||
|
files = [
|
||||||
|
{file = "pydantic-2.9.2-py3-none-any.whl", hash = "sha256:f048cec7b26778210e28a0459867920654d48e5e62db0958433636cde4254f12"},
|
||||||
|
{file = "pydantic-2.9.2.tar.gz", hash = "sha256:d155cef71265d1e9807ed1c32b4c8deec042a44a50a4188b25ac67ecd81a9c0f"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pydantic-core"
|
||||||
|
version = "2.23.4"
|
||||||
|
requires_python = ">=3.8"
|
||||||
|
summary = "Core functionality for Pydantic validation and serialization"
|
||||||
|
groups = ["default"]
|
||||||
|
dependencies = [
|
||||||
|
"typing-extensions!=4.7.0,>=4.6.0",
|
||||||
|
]
|
||||||
|
files = [
|
||||||
|
{file = "pydantic_core-2.23.4-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:b10bd51f823d891193d4717448fab065733958bdb6a6b351967bd349d48d5c9b"},
|
||||||
|
{file = "pydantic_core-2.23.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:4fc714bdbfb534f94034efaa6eadd74e5b93c8fa6315565a222f7b6f42ca1166"},
|
||||||
|
{file = "pydantic_core-2.23.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:63e46b3169866bd62849936de036f901a9356e36376079b05efa83caeaa02ceb"},
|
||||||
|
{file = "pydantic_core-2.23.4-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ed1a53de42fbe34853ba90513cea21673481cd81ed1be739f7f2efb931b24916"},
|
||||||
|
{file = "pydantic_core-2.23.4-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:cfdd16ab5e59fc31b5e906d1a3f666571abc367598e3e02c83403acabc092e07"},
|
||||||
|
{file = "pydantic_core-2.23.4-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:255a8ef062cbf6674450e668482456abac99a5583bbafb73f9ad469540a3a232"},
|
||||||
|
{file = "pydantic_core-2.23.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4a7cd62e831afe623fbb7aabbb4fe583212115b3ef38a9f6b71869ba644624a2"},
|
||||||
|
{file = "pydantic_core-2.23.4-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:f09e2ff1f17c2b51f2bc76d1cc33da96298f0a036a137f5440ab3ec5360b624f"},
|
||||||
|
{file = "pydantic_core-2.23.4-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:e38e63e6f3d1cec5a27e0afe90a085af8b6806ee208b33030e65b6516353f1a3"},
|
||||||
|
{file = "pydantic_core-2.23.4-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:0dbd8dbed2085ed23b5c04afa29d8fd2771674223135dc9bc937f3c09284d071"},
|
||||||
|
{file = "pydantic_core-2.23.4-cp310-none-win32.whl", hash = "sha256:6531b7ca5f951d663c339002e91aaebda765ec7d61b7d1e3991051906ddde119"},
|
||||||
|
{file = "pydantic_core-2.23.4-cp310-none-win_amd64.whl", hash = "sha256:7c9129eb40958b3d4500fa2467e6a83356b3b61bfff1b414c7361d9220f9ae8f"},
|
||||||
|
{file = "pydantic_core-2.23.4-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:77733e3892bb0a7fa797826361ce8a9184d25c8dffaec60b7ffe928153680ba8"},
|
||||||
|
{file = "pydantic_core-2.23.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:1b84d168f6c48fabd1f2027a3d1bdfe62f92cade1fb273a5d68e621da0e44e6d"},
|
||||||
|
{file = "pydantic_core-2.23.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:df49e7a0861a8c36d089c1ed57d308623d60416dab2647a4a17fe050ba85de0e"},
|
||||||
|
{file = "pydantic_core-2.23.4-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ff02b6d461a6de369f07ec15e465a88895f3223eb75073ffea56b84d9331f607"},
|
||||||
|
{file = "pydantic_core-2.23.4-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:996a38a83508c54c78a5f41456b0103c30508fed9abcad0a59b876d7398f25fd"},
|
||||||
|
{file = "pydantic_core-2.23.4-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d97683ddee4723ae8c95d1eddac7c192e8c552da0c73a925a89fa8649bf13eea"},
|
||||||
|
{file = "pydantic_core-2.23.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:216f9b2d7713eb98cb83c80b9c794de1f6b7e3145eef40400c62e86cee5f4e1e"},
|
||||||
|
{file = "pydantic_core-2.23.4-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:6f783e0ec4803c787bcea93e13e9932edab72068f68ecffdf86a99fd5918878b"},
|
||||||
|
{file = "pydantic_core-2.23.4-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:d0776dea117cf5272382634bd2a5c1b6eb16767c223c6a5317cd3e2a757c61a0"},
|
||||||
|
{file = "pydantic_core-2.23.4-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:d5f7a395a8cf1621939692dba2a6b6a830efa6b3cee787d82c7de1ad2930de64"},
|
||||||
|
{file = "pydantic_core-2.23.4-cp311-none-win32.whl", hash = "sha256:74b9127ffea03643e998e0c5ad9bd3811d3dac8c676e47db17b0ee7c3c3bf35f"},
|
||||||
|
{file = "pydantic_core-2.23.4-cp311-none-win_amd64.whl", hash = "sha256:98d134c954828488b153d88ba1f34e14259284f256180ce659e8d83e9c05eaa3"},
|
||||||
|
{file = "pydantic_core-2.23.4-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:f3e0da4ebaef65158d4dfd7d3678aad692f7666877df0002b8a522cdf088f231"},
|
||||||
|
{file = "pydantic_core-2.23.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:f69a8e0b033b747bb3e36a44e7732f0c99f7edd5cea723d45bc0d6e95377ffee"},
|
||||||
|
{file = "pydantic_core-2.23.4-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:723314c1d51722ab28bfcd5240d858512ffd3116449c557a1336cbe3919beb87"},
|
||||||
|
{file = "pydantic_core-2.23.4-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:bb2802e667b7051a1bebbfe93684841cc9351004e2badbd6411bf357ab8d5ac8"},
|
||||||
|
{file = "pydantic_core-2.23.4-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d18ca8148bebe1b0a382a27a8ee60350091a6ddaf475fa05ef50dc35b5df6327"},
|
||||||
|
{file = "pydantic_core-2.23.4-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:33e3d65a85a2a4a0dc3b092b938a4062b1a05f3a9abde65ea93b233bca0e03f2"},
|
||||||
|
{file = "pydantic_core-2.23.4-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:128585782e5bfa515c590ccee4b727fb76925dd04a98864182b22e89a4e6ed36"},
|
||||||
|
{file = "pydantic_core-2.23.4-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:68665f4c17edcceecc112dfed5dbe6f92261fb9d6054b47d01bf6371a6196126"},
|
||||||
|
{file = "pydantic_core-2.23.4-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:20152074317d9bed6b7a95ade3b7d6054845d70584216160860425f4fbd5ee9e"},
|
||||||
|
{file = "pydantic_core-2.23.4-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:9261d3ce84fa1d38ed649c3638feefeae23d32ba9182963e465d58d62203bd24"},
|
||||||
|
{file = "pydantic_core-2.23.4-cp312-none-win32.whl", hash = "sha256:4ba762ed58e8d68657fc1281e9bb72e1c3e79cc5d464be146e260c541ec12d84"},
|
||||||
|
{file = "pydantic_core-2.23.4-cp312-none-win_amd64.whl", hash = "sha256:97df63000f4fea395b2824da80e169731088656d1818a11b95f3b173747b6cd9"},
|
||||||
|
{file = "pydantic_core-2.23.4-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:7530e201d10d7d14abce4fb54cfe5b94a0aefc87da539d0346a484ead376c3cc"},
|
||||||
|
{file = "pydantic_core-2.23.4-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:df933278128ea1cd77772673c73954e53a1c95a4fdf41eef97c2b779271bd0bd"},
|
||||||
|
{file = "pydantic_core-2.23.4-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0cb3da3fd1b6a5d0279a01877713dbda118a2a4fc6f0d821a57da2e464793f05"},
|
||||||
|
{file = "pydantic_core-2.23.4-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:42c6dcb030aefb668a2b7009c85b27f90e51e6a3b4d5c9bc4c57631292015b0d"},
|
||||||
|
{file = "pydantic_core-2.23.4-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:696dd8d674d6ce621ab9d45b205df149399e4bb9aa34102c970b721554828510"},
|
||||||
|
{file = "pydantic_core-2.23.4-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2971bb5ffe72cc0f555c13e19b23c85b654dd2a8f7ab493c262071377bfce9f6"},
|
||||||
|
{file = "pydantic_core-2.23.4-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8394d940e5d400d04cad4f75c0598665cbb81aecefaca82ca85bd28264af7f9b"},
|
||||||
|
{file = "pydantic_core-2.23.4-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:0dff76e0602ca7d4cdaacc1ac4c005e0ce0dcfe095d5b5259163a80d3a10d327"},
|
||||||
|
{file = "pydantic_core-2.23.4-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:7d32706badfe136888bdea71c0def994644e09fff0bfe47441deaed8e96fdbc6"},
|
||||||
|
{file = "pydantic_core-2.23.4-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:ed541d70698978a20eb63d8c5d72f2cc6d7079d9d90f6b50bad07826f1320f5f"},
|
||||||
|
{file = "pydantic_core-2.23.4-cp313-none-win32.whl", hash = "sha256:3d5639516376dce1940ea36edf408c554475369f5da2abd45d44621cb616f769"},
|
||||||
|
{file = "pydantic_core-2.23.4-cp313-none-win_amd64.whl", hash = "sha256:5a1504ad17ba4210df3a045132a7baeeba5a200e930f57512ee02909fc5c4cb5"},
|
||||||
|
{file = "pydantic_core-2.23.4-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:f455ee30a9d61d3e1a15abd5068827773d6e4dc513e795f380cdd59932c782d5"},
|
||||||
|
{file = "pydantic_core-2.23.4-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:1e90d2e3bd2c3863d48525d297cd143fe541be8bbf6f579504b9712cb6b643ec"},
|
||||||
|
{file = "pydantic_core-2.23.4-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2e203fdf807ac7e12ab59ca2bfcabb38c7cf0b33c41efeb00f8e5da1d86af480"},
|
||||||
|
{file = "pydantic_core-2.23.4-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e08277a400de01bc72436a0ccd02bdf596631411f592ad985dcee21445bd0068"},
|
||||||
|
{file = "pydantic_core-2.23.4-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:f220b0eea5965dec25480b6333c788fb72ce5f9129e8759ef876a1d805d00801"},
|
||||||
|
{file = "pydantic_core-2.23.4-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:d06b0c8da4f16d1d1e352134427cb194a0a6e19ad5db9161bf32b2113409e728"},
|
||||||
|
{file = "pydantic_core-2.23.4-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:ba1a0996f6c2773bd83e63f18914c1de3c9dd26d55f4ac302a7efe93fb8e7433"},
|
||||||
|
{file = "pydantic_core-2.23.4-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:9a5bce9d23aac8f0cf0836ecfc033896aa8443b501c58d0602dbfd5bd5b37753"},
|
||||||
|
{file = "pydantic_core-2.23.4.tar.gz", hash = "sha256:2584f7cf844ac4d970fba483a717dbe10c1c1c96a969bf65d61ffe94df1b2863"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pytest"
|
||||||
|
version = "8.3.3"
|
||||||
|
requires_python = ">=3.8"
|
||||||
|
summary = "pytest: simple powerful testing with Python"
|
||||||
|
groups = ["dev"]
|
||||||
|
dependencies = [
|
||||||
|
"colorama; sys_platform == \"win32\"",
|
||||||
|
"exceptiongroup>=1.0.0rc8; python_version < \"3.11\"",
|
||||||
|
"iniconfig",
|
||||||
|
"packaging",
|
||||||
|
"pluggy<2,>=1.5",
|
||||||
|
"tomli>=1; python_version < \"3.11\"",
|
||||||
|
]
|
||||||
|
files = [
|
||||||
|
{file = "pytest-8.3.3-py3-none-any.whl", hash = "sha256:a6853c7375b2663155079443d2e45de913a911a11d669df02a50814944db57b2"},
|
||||||
|
{file = "pytest-8.3.3.tar.gz", hash = "sha256:70b98107bd648308a7952b06e6ca9a50bc660be218d53c257cc1fc94fda10181"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pyyaml"
|
||||||
|
version = "6.0.2"
|
||||||
|
requires_python = ">=3.8"
|
||||||
|
summary = "YAML parser and emitter for Python"
|
||||||
|
groups = ["default"]
|
||||||
|
files = [
|
||||||
|
{file = "PyYAML-6.0.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:0a9a2848a5b7feac301353437eb7d5957887edbf81d56e903999a75a3d743086"},
|
||||||
|
{file = "PyYAML-6.0.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:29717114e51c84ddfba879543fb232a6ed60086602313ca38cce623c1d62cfbf"},
|
||||||
|
{file = "PyYAML-6.0.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8824b5a04a04a047e72eea5cec3bc266db09e35de6bdfe34c9436ac5ee27d237"},
|
||||||
|
{file = "PyYAML-6.0.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7c36280e6fb8385e520936c3cb3b8042851904eba0e58d277dca80a5cfed590b"},
|
||||||
|
{file = "PyYAML-6.0.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ec031d5d2feb36d1d1a24380e4db6d43695f3748343d99434e6f5f9156aaa2ed"},
|
||||||
|
{file = "PyYAML-6.0.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:936d68689298c36b53b29f23c6dbb74de12b4ac12ca6cfe0e047bedceea56180"},
|
||||||
|
{file = "PyYAML-6.0.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:23502f431948090f597378482b4812b0caae32c22213aecf3b55325e049a6c68"},
|
||||||
|
{file = "PyYAML-6.0.2-cp310-cp310-win32.whl", hash = "sha256:2e99c6826ffa974fe6e27cdb5ed0021786b03fc98e5ee3c5bfe1fd5015f42b99"},
|
||||||
|
{file = "PyYAML-6.0.2-cp310-cp310-win_amd64.whl", hash = "sha256:a4d3091415f010369ae4ed1fc6b79def9416358877534caf6a0fdd2146c87a3e"},
|
||||||
|
{file = "PyYAML-6.0.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:cc1c1159b3d456576af7a3e4d1ba7e6924cb39de8f67111c735f6fc832082774"},
|
||||||
|
{file = "PyYAML-6.0.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:1e2120ef853f59c7419231f3bf4e7021f1b936f6ebd222406c3b60212205d2ee"},
|
||||||
|
{file = "PyYAML-6.0.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5d225db5a45f21e78dd9358e58a98702a0302f2659a3c6cd320564b75b86f47c"},
|
||||||
|
{file = "PyYAML-6.0.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5ac9328ec4831237bec75defaf839f7d4564be1e6b25ac710bd1a96321cc8317"},
|
||||||
|
{file = "PyYAML-6.0.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3ad2a3decf9aaba3d29c8f537ac4b243e36bef957511b4766cb0057d32b0be85"},
|
||||||
|
{file = "PyYAML-6.0.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:ff3824dc5261f50c9b0dfb3be22b4567a6f938ccce4587b38952d85fd9e9afe4"},
|
||||||
|
{file = "PyYAML-6.0.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:797b4f722ffa07cc8d62053e4cff1486fa6dc094105d13fea7b1de7d8bf71c9e"},
|
||||||
|
{file = "PyYAML-6.0.2-cp311-cp311-win32.whl", hash = "sha256:11d8f3dd2b9c1207dcaf2ee0bbbfd5991f571186ec9cc78427ba5bd32afae4b5"},
|
||||||
|
{file = "PyYAML-6.0.2-cp311-cp311-win_amd64.whl", hash = "sha256:e10ce637b18caea04431ce14fabcf5c64a1c61ec9c56b071a4b7ca131ca52d44"},
|
||||||
|
{file = "PyYAML-6.0.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:c70c95198c015b85feafc136515252a261a84561b7b1d51e3384e0655ddf25ab"},
|
||||||
|
{file = "PyYAML-6.0.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ce826d6ef20b1bc864f0a68340c8b3287705cae2f8b4b1d932177dcc76721725"},
|
||||||
|
{file = "PyYAML-6.0.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1f71ea527786de97d1a0cc0eacd1defc0985dcf6b3f17bb77dcfc8c34bec4dc5"},
|
||||||
|
{file = "PyYAML-6.0.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9b22676e8097e9e22e36d6b7bda33190d0d400f345f23d4065d48f4ca7ae0425"},
|
||||||
|
{file = "PyYAML-6.0.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:80bab7bfc629882493af4aa31a4cfa43a4c57c83813253626916b8c7ada83476"},
|
||||||
|
{file = "PyYAML-6.0.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:0833f8694549e586547b576dcfaba4a6b55b9e96098b36cdc7ebefe667dfed48"},
|
||||||
|
{file = "PyYAML-6.0.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8b9c7197f7cb2738065c481a0461e50ad02f18c78cd75775628afb4d7137fb3b"},
|
||||||
|
{file = "PyYAML-6.0.2-cp312-cp312-win32.whl", hash = "sha256:ef6107725bd54b262d6dedcc2af448a266975032bc85ef0172c5f059da6325b4"},
|
||||||
|
{file = "PyYAML-6.0.2-cp312-cp312-win_amd64.whl", hash = "sha256:7e7401d0de89a9a855c839bc697c079a4af81cf878373abd7dc625847d25cbd8"},
|
||||||
|
{file = "PyYAML-6.0.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:efdca5630322a10774e8e98e1af481aad470dd62c3170801852d752aa7a783ba"},
|
||||||
|
{file = "PyYAML-6.0.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:50187695423ffe49e2deacb8cd10510bc361faac997de9efef88badc3bb9e2d1"},
|
||||||
|
{file = "PyYAML-6.0.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0ffe8360bab4910ef1b9e87fb812d8bc0a308b0d0eef8c8f44e0254ab3b07133"},
|
||||||
|
{file = "PyYAML-6.0.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:17e311b6c678207928d649faa7cb0d7b4c26a0ba73d41e99c4fff6b6c3276484"},
|
||||||
|
{file = "PyYAML-6.0.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:70b189594dbe54f75ab3a1acec5f1e3faa7e8cf2f1e08d9b561cb41b845f69d5"},
|
||||||
|
{file = "PyYAML-6.0.2-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:41e4e3953a79407c794916fa277a82531dd93aad34e29c2a514c2c0c5fe971cc"},
|
||||||
|
{file = "PyYAML-6.0.2-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:68ccc6023a3400877818152ad9a1033e3db8625d899c72eacb5a668902e4d652"},
|
||||||
|
{file = "PyYAML-6.0.2-cp313-cp313-win32.whl", hash = "sha256:bc2fa7c6b47d6bc618dd7fb02ef6fdedb1090ec036abab80d4681424b84c1183"},
|
||||||
|
{file = "PyYAML-6.0.2-cp313-cp313-win_amd64.whl", hash = "sha256:8388ee1976c416731879ac16da0aff3f63b286ffdd57cdeb95f3f2e085687563"},
|
||||||
|
{file = "pyyaml-6.0.2.tar.gz", hash = "sha256:d584d9ec91ad65861cc08d42e834324ef890a082e591037abe114850ff7bbc3e"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "toml"
|
||||||
|
version = "0.10.2"
|
||||||
|
requires_python = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*"
|
||||||
|
summary = "Python Library for Tom's Obvious, Minimal Language"
|
||||||
|
groups = ["default"]
|
||||||
|
files = [
|
||||||
|
{file = "toml-0.10.2-py2.py3-none-any.whl", hash = "sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b"},
|
||||||
|
{file = "toml-0.10.2.tar.gz", hash = "sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tomli"
|
||||||
|
version = "2.0.2"
|
||||||
|
requires_python = ">=3.8"
|
||||||
|
summary = "A lil' TOML parser"
|
||||||
|
groups = ["dev"]
|
||||||
|
marker = "python_version < \"3.11\""
|
||||||
|
files = [
|
||||||
|
{file = "tomli-2.0.2-py3-none-any.whl", hash = "sha256:2ebe24485c53d303f690b0ec092806a085f07af5a5aa1464f3931eec36caaa38"},
|
||||||
|
{file = "tomli-2.0.2.tar.gz", hash = "sha256:d46d457a85337051c36524bc5349dd91b1877838e2979ac5ced3e710ed8a60ed"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "typing-extensions"
|
||||||
|
version = "4.12.2"
|
||||||
|
requires_python = ">=3.8"
|
||||||
|
summary = "Backported and Experimental Type Hints for Python 3.8+"
|
||||||
|
groups = ["default", "dev"]
|
||||||
|
files = [
|
||||||
|
{file = "typing_extensions-4.12.2-py3-none-any.whl", hash = "sha256:04e5ca0351e0f3f85c6853954072df659d0d13fac324d0072316b67d7794700d"},
|
||||||
|
{file = "typing_extensions-4.12.2.tar.gz", hash = "sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "uv"
|
||||||
|
version = "0.4.20"
|
||||||
|
requires_python = ">=3.8"
|
||||||
|
summary = "An extremely fast Python package and project manager, written in Rust."
|
||||||
|
groups = ["dev"]
|
||||||
|
files = [
|
||||||
|
{file = "uv-0.4.20-py3-none-linux_armv6l.whl", hash = "sha256:d0566f3ce596b0192099f7a01be08e1f37061d7399e0128804794cf83cdf2806"},
|
||||||
|
{file = "uv-0.4.20-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:1f20251b5a6a1cc92d844153b128b346bd0be8178beb4945df63d1a76a905176"},
|
||||||
|
{file = "uv-0.4.20-py3-none-macosx_11_0_arm64.whl", hash = "sha256:d37f02ae48540104d9c13d2dfe27bf84b246d5945b55d91568404da08e2a3bd8"},
|
||||||
|
{file = "uv-0.4.20-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.musllinux_1_1_aarch64.whl", hash = "sha256:555f0275c3db5b1cd13f6a6825b0b0f23e116a58a46da65f55d4f07915b36b16"},
|
||||||
|
{file = "uv-0.4.20-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:a6faba47d13c1b916bfe9a1828a792ba21558871b4b81dbb79c157077f558fb3"},
|
||||||
|
{file = "uv-0.4.20-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:092d4d3cee4a9680832c16d5c1a5e816b2d07a31328580f04e4ddf437821b1f3"},
|
||||||
|
{file = "uv-0.4.20-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:5d62655450d173a4dbe76b70b9af81ffa501501d97224f311f126b30924b42f7"},
|
||||||
|
{file = "uv-0.4.20-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:865c5fbc2ebe73b4f4b71cbcc1b1bae90a335b15f6eaa9fa6495f77a6e86455e"},
|
||||||
|
{file = "uv-0.4.20-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a65eaec88b084094f5b08c2ad73f0ae972f7d6afd0d3ee1d0eb29a76c010a39b"},
|
||||||
|
{file = "uv-0.4.20-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b8e3492d5f1613e88201b6f68a2e5fba48b0bdbe0f11179df9b222e9dd8d89d3"},
|
||||||
|
{file = "uv-0.4.20-py3-none-manylinux_2_28_aarch64.whl", hash = "sha256:8ec4a7d0ab131ea749702d4885ff0f6734e1aca1dc26ebbc1c7c67969ba3c0fc"},
|
||||||
|
{file = "uv-0.4.20-py3-none-musllinux_1_1_armv7l.whl", hash = "sha256:588aedc47fe02f8cf0dfe0dec3fd5e1f3a707fdf674964b3d31f0523351db9d2"},
|
||||||
|
{file = "uv-0.4.20-py3-none-musllinux_1_1_i686.whl", hash = "sha256:309539e9b29f3fbbedb3835297a324a9206b42005e15b0af3fa73343ab966349"},
|
||||||
|
{file = "uv-0.4.20-py3-none-musllinux_1_1_ppc64le.whl", hash = "sha256:8ad94fb135bec5c061ba21b1f081f349c3de2b0f8660e168e5afc829d3069e6d"},
|
||||||
|
{file = "uv-0.4.20-py3-none-musllinux_1_1_x86_64.whl", hash = "sha256:74f78748e72893a674351ca9d708003629ddc1a00bc51100c901b5d47db73e43"},
|
||||||
|
{file = "uv-0.4.20-py3-none-win32.whl", hash = "sha256:dbf454b6f56f9181886426c7aed7a8dfc8258f80082365fe99b2044ff92261ba"},
|
||||||
|
{file = "uv-0.4.20-py3-none-win_amd64.whl", hash = "sha256:653bfec188d199384451804a6c055fb1d28662adfee7697fe7108c6fb78924ba"},
|
||||||
|
{file = "uv-0.4.20.tar.gz", hash = "sha256:b4c8a2027b1f19f8b8949132e728a750e4f9b4bb0ec02544d9b21df3f525ab1a"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "watchdog"
|
||||||
|
version = "5.0.3"
|
||||||
|
requires_python = ">=3.9"
|
||||||
|
summary = "Filesystem events monitoring"
|
||||||
|
groups = ["default"]
|
||||||
|
files = [
|
||||||
|
{file = "watchdog-5.0.3-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:85527b882f3facda0579bce9d743ff7f10c3e1e0db0a0d0e28170a7d0e5ce2ea"},
|
||||||
|
{file = "watchdog-5.0.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:53adf73dcdc0ef04f7735066b4a57a4cd3e49ef135daae41d77395f0b5b692cb"},
|
||||||
|
{file = "watchdog-5.0.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:e25adddab85f674acac303cf1f5835951345a56c5f7f582987d266679979c75b"},
|
||||||
|
{file = "watchdog-5.0.3-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:f01f4a3565a387080dc49bdd1fefe4ecc77f894991b88ef927edbfa45eb10818"},
|
||||||
|
{file = "watchdog-5.0.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:91b522adc25614cdeaf91f7897800b82c13b4b8ac68a42ca959f992f6990c490"},
|
||||||
|
{file = "watchdog-5.0.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:d52db5beb5e476e6853da2e2d24dbbbed6797b449c8bf7ea118a4ee0d2c9040e"},
|
||||||
|
{file = "watchdog-5.0.3-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:94d11b07c64f63f49876e0ab8042ae034674c8653bfcdaa8c4b32e71cfff87e8"},
|
||||||
|
{file = "watchdog-5.0.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:349c9488e1d85d0a58e8cb14222d2c51cbc801ce11ac3936ab4c3af986536926"},
|
||||||
|
{file = "watchdog-5.0.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:53a3f10b62c2d569e260f96e8d966463dec1a50fa4f1b22aec69e3f91025060e"},
|
||||||
|
{file = "watchdog-5.0.3-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:950f531ec6e03696a2414b6308f5c6ff9dab7821a768c9d5788b1314e9a46ca7"},
|
||||||
|
{file = "watchdog-5.0.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:ae6deb336cba5d71476caa029ceb6e88047fc1dc74b62b7c4012639c0b563906"},
|
||||||
|
{file = "watchdog-5.0.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:1021223c08ba8d2d38d71ec1704496471ffd7be42cfb26b87cd5059323a389a1"},
|
||||||
|
{file = "watchdog-5.0.3-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:90a67d7857adb1d985aca232cc9905dd5bc4803ed85cfcdcfcf707e52049eda7"},
|
||||||
|
{file = "watchdog-5.0.3-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:720ef9d3a4f9ca575a780af283c8fd3a0674b307651c1976714745090da5a9e8"},
|
||||||
|
{file = "watchdog-5.0.3-py3-none-manylinux2014_aarch64.whl", hash = "sha256:dd021efa85970bd4824acacbb922066159d0f9e546389a4743d56919b6758b91"},
|
||||||
|
{file = "watchdog-5.0.3-py3-none-manylinux2014_armv7l.whl", hash = "sha256:78864cc8f23dbee55be34cc1494632a7ba30263951b5b2e8fc8286b95845f82c"},
|
||||||
|
{file = "watchdog-5.0.3-py3-none-manylinux2014_i686.whl", hash = "sha256:1e9679245e3ea6498494b3028b90c7b25dbb2abe65c7d07423ecfc2d6218ff7c"},
|
||||||
|
{file = "watchdog-5.0.3-py3-none-manylinux2014_ppc64.whl", hash = "sha256:9413384f26b5d050b6978e6fcd0c1e7f0539be7a4f1a885061473c5deaa57221"},
|
||||||
|
{file = "watchdog-5.0.3-py3-none-manylinux2014_ppc64le.whl", hash = "sha256:294b7a598974b8e2c6123d19ef15de9abcd282b0fbbdbc4d23dfa812959a9e05"},
|
||||||
|
{file = "watchdog-5.0.3-py3-none-manylinux2014_s390x.whl", hash = "sha256:26dd201857d702bdf9d78c273cafcab5871dd29343748524695cecffa44a8d97"},
|
||||||
|
{file = "watchdog-5.0.3-py3-none-manylinux2014_x86_64.whl", hash = "sha256:0f9332243355643d567697c3e3fa07330a1d1abf981611654a1f2bf2175612b7"},
|
||||||
|
{file = "watchdog-5.0.3-py3-none-win32.whl", hash = "sha256:c66f80ee5b602a9c7ab66e3c9f36026590a0902db3aea414d59a2f55188c1f49"},
|
||||||
|
{file = "watchdog-5.0.3-py3-none-win_amd64.whl", hash = "sha256:f00b4cf737f568be9665563347a910f8bdc76f88c2970121c86243c8cfdf90e9"},
|
||||||
|
{file = "watchdog-5.0.3-py3-none-win_ia64.whl", hash = "sha256:49f4d36cb315c25ea0d946e018c01bb028048023b9e103d3d3943f58e109dd45"},
|
||||||
|
{file = "watchdog-5.0.3.tar.gz", hash = "sha256:108f42a7f0345042a854d4d0ad0834b741d421330d5f575b81cb27b883500176"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "win32-setctime"
|
||||||
|
version = "1.1.0"
|
||||||
|
requires_python = ">=3.5"
|
||||||
|
summary = "A small Python utility to set file creation time on Windows"
|
||||||
|
groups = ["default"]
|
||||||
|
marker = "sys_platform == \"win32\""
|
||||||
|
files = [
|
||||||
|
{file = "win32_setctime-1.1.0-py3-none-any.whl", hash = "sha256:231db239e959c2fe7eb1d7dc129f11172354f98361c4fa2d6d2d7e278baa8aad"},
|
||||||
|
{file = "win32_setctime-1.1.0.tar.gz", hash = "sha256:15cf5750465118d6929ae4de4eb46e8edae9a5634350c01ba582df868e932cb2"},
|
||||||
|
]
|
@@ -10,17 +10,18 @@ readme = "README.md"
|
|||||||
requires-python = ">=3.10"
|
requires-python = ">=3.10"
|
||||||
authors = [
|
authors = [
|
||||||
{ name = "snowykami", email = "snowykami@outlook.com" },
|
{ name = "snowykami", email = "snowykami@outlook.com" },
|
||||||
{ name = "LiteyukiStudio", email = "studio@liteyuki.icu" },
|
|
||||||
]
|
]
|
||||||
license = { text = "MIT&LSO" }
|
license = { text = "MIT&LSO" }
|
||||||
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"loguru~=0.7.2",
|
"loguru~=0.7.2",
|
||||||
"pydantic==2.8.2",
|
"pydantic>=2.8.2",
|
||||||
"PyYAML==6.0.2",
|
"PyYAML>=6.0.2",
|
||||||
"toml==0.10.2",
|
"toml>=0.10.2",
|
||||||
"watchdog==4.0.1",
|
"watchdog>=4.0.1",
|
||||||
"pdm-backend==2.3.3"
|
"pdm-backend>=2.3.3",
|
||||||
|
"magicoca>=1.0.1",
|
||||||
|
"croterline>=1.0.3"
|
||||||
]
|
]
|
||||||
|
|
||||||
[project.urls]
|
[project.urls]
|
||||||
@@ -38,5 +39,14 @@ includes = ["liteyuki/", "LICENSE", "README.md"]
|
|||||||
excludes = ["tests/", "docs/", "src/"]
|
excludes = ["tests/", "docs/", "src/"]
|
||||||
|
|
||||||
[tool.pdm.version]
|
[tool.pdm.version]
|
||||||
source = "file"
|
source = "scm"
|
||||||
path = "liteyuki/__init__.py"
|
tag_filter = "v*"
|
||||||
|
tag_regex = '^v(?:\D*)?(?P<version>([1-9][0-9]*!)?(0|[1-9][0-9]*)(\.(0|[1-9][0-9]*))*((a|b|c|rc)(0|[1-9][0-9]*))?(\.post(0|[1-9][0-9]*))?(\.dev(0|[1-9][0-9]*))?$)$'
|
||||||
|
|
||||||
|
[tool.pdm.dev-dependencies]
|
||||||
|
dev = [
|
||||||
|
"pytest>=8.3.3",
|
||||||
|
"black>=24.10.0",
|
||||||
|
"uv>=0.4.20",
|
||||||
|
"mypy>=1.11.2",
|
||||||
|
]
|
||||||
|
@@ -1,6 +1,7 @@
|
|||||||
aiohttp>=3.9.3
|
aiohttp>=3.9.3
|
||||||
aiofiles>=23.2.1
|
aiofiles>=23.2.1
|
||||||
colored>=2.2.4
|
colored>=2.2.4
|
||||||
|
croterline>=1.0.3
|
||||||
GitPython>=3.1.43
|
GitPython>=3.1.43
|
||||||
httpx>=0.27.0
|
httpx>=0.27.0
|
||||||
nonebot-plugin-htmlrender>=0.1.0
|
nonebot-plugin-htmlrender>=0.1.0
|
||||||
@@ -26,3 +27,8 @@ importlib_metadata>=7.0.2
|
|||||||
watchdog>=4.0.0
|
watchdog>=4.0.0
|
||||||
jieba>=0.42.1
|
jieba>=0.42.1
|
||||||
python-dotenv>=1.0.1
|
python-dotenv>=1.0.1
|
||||||
|
loguru~=0.7.2
|
||||||
|
pydantic~=2.9.2
|
||||||
|
pip~=23.2.1
|
||||||
|
fastapi~=0.115.0
|
||||||
|
magicoca~=1.0.1
|
@@ -1,53 +0,0 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
"""
|
|
||||||
Copyright (C) 2020-2024 LiteyukiStudio. All Rights Reserved
|
|
||||||
|
|
||||||
@Time : 2024/8/11 下午5:24
|
|
||||||
@Author : snowykami
|
|
||||||
@Email : snowykami@outlook.com
|
|
||||||
@File : __init__.py.py
|
|
||||||
@Software: PyCharm
|
|
||||||
"""
|
|
||||||
|
|
||||||
import nonebot
|
|
||||||
from liteyuki.utils import IS_MAIN_PROCESS
|
|
||||||
from liteyuki.plugin import PluginMetadata, PluginType
|
|
||||||
from .nb_utils import adapter_manager, driver_manager # type: ignore
|
|
||||||
from liteyuki.log import logger
|
|
||||||
|
|
||||||
__plugin_meta__ = PluginMetadata(
|
|
||||||
name="NoneBot2启动器",
|
|
||||||
type=PluginType.APPLICATION,
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def nb_run(*args, **kwargs):
|
|
||||||
"""
|
|
||||||
初始化NoneBot并运行在子进程
|
|
||||||
Args:
|
|
||||||
**kwargs:
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
"""
|
|
||||||
# 给子进程传递通道对象
|
|
||||||
kwargs.update(kwargs.get("nonebot", {})) # nonebot配置优先
|
|
||||||
nonebot.init(**kwargs)
|
|
||||||
|
|
||||||
driver_manager.init(config=kwargs)
|
|
||||||
adapter_manager.init(kwargs)
|
|
||||||
adapter_manager.register()
|
|
||||||
|
|
||||||
try:
|
|
||||||
# nonebot.load_plugin("nonebot-plugin-lnpm") # 尝试加载轻雪NoneBot插件加载器(Nonebot插件)
|
|
||||||
nonebot.load_plugin("src.liteyuki_main") # 尝试加载轻雪主插件(Nonebot插件)
|
|
||||||
except Exception as e:
|
|
||||||
pass
|
|
||||||
nonebot.run()
|
|
||||||
|
|
||||||
|
|
||||||
if IS_MAIN_PROCESS:
|
|
||||||
from liteyuki import get_bot
|
|
||||||
from .dev_reloader import *
|
|
||||||
|
|
||||||
liteyuki = get_bot()
|
|
||||||
liteyuki.process_manager.add_target(name="nonebot", target=nb_run, args=(), kwargs=liteyuki.config)
|
|
33
src/liteyuki_plugins/nonebot/__init__.py
Normal file
33
src/liteyuki_plugins/nonebot/__init__.py
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
import os.path
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
import nonebot
|
||||||
|
from croterline.utils import IsMainProcess
|
||||||
|
|
||||||
|
from liteyuki import get_bot
|
||||||
|
from liteyuki.core import sub_process_manager
|
||||||
|
from liteyuki.plugin import PluginMetadata, PluginType
|
||||||
|
|
||||||
|
__plugin_meta__ = PluginMetadata(
|
||||||
|
name="NoneBot2启动器",
|
||||||
|
type=PluginType.APPLICATION,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def nb_run(*args, **kwargs):
|
||||||
|
nonebot.init(**kwargs)
|
||||||
|
|
||||||
|
from .nb_utils import driver_manager, adapter_manager
|
||||||
|
driver_manager.init(config=kwargs)
|
||||||
|
adapter_manager.init(kwargs)
|
||||||
|
adapter_manager.register()
|
||||||
|
nonebot.load_plugin(Path(os.path.dirname(__file__)) / "np_main")
|
||||||
|
nonebot.run()
|
||||||
|
|
||||||
|
|
||||||
|
if IsMainProcess:
|
||||||
|
from .dev_reloader import *
|
||||||
|
bot = get_bot()
|
||||||
|
sub_process_manager.add(
|
||||||
|
name="nonebot", func=nb_run, **bot.config.get("nonebot", {})
|
||||||
|
)
|
@@ -10,15 +10,17 @@ from liteyuki.utils import IS_MAIN_PROCESS
|
|||||||
from watchdog.events import FileSystemEvent
|
from watchdog.events import FileSystemEvent
|
||||||
|
|
||||||
|
|
||||||
liteyuki = get_bot()
|
bot = get_bot()
|
||||||
|
|
||||||
exclude_extensions = (".pyc", ".pyo")
|
exclude_extensions = (".pyc", ".pyo")
|
||||||
|
|
||||||
|
|
||||||
@observer.on_file_system_event(
|
@observer.on_file_system_event(
|
||||||
directories=("src/nonebot_plugins",),
|
directories=("src/nonebot_plugins",),
|
||||||
event_filter=lambda event: not event.src_path.endswith(exclude_extensions) and ("__pycache__" not in event.src_path ) and os.path.isfile(event.src_path)
|
event_filter=lambda event: not event.src_path.endswith(exclude_extensions)
|
||||||
|
and ("__pycache__" not in event.src_path)
|
||||||
|
and os.path.isfile(event.src_path),
|
||||||
)
|
)
|
||||||
def restart_nonebot_process(event: FileSystemEvent):
|
def restart_nonebot_process(event: FileSystemEvent):
|
||||||
logger.debug(f"File {event.src_path} changed, reloading nonebot...")
|
logger.debug(f"File {event.src_path} changed, reloading nonebot...")
|
||||||
liteyuki.restart_process("nonebot")
|
bot.restart_process("nonebot")
|
@@ -10,7 +10,7 @@ from .common import MessageEventModel, msg_db
|
|||||||
from src.utils.base.language import Language
|
from src.utils.base.language import Language
|
||||||
from src.utils.base.resource import get_path
|
from src.utils.base.resource import get_path
|
||||||
from src.utils.message.string_tool import convert_seconds_to_time
|
from src.utils.message.string_tool import convert_seconds_to_time
|
||||||
from ...utils.external.logo import get_group_icon, get_user_icon
|
from src.utils.external.logo import get_group_icon, get_user_icon
|
||||||
|
|
||||||
|
|
||||||
async def count_msg_by_bot_id(bot_id: str) -> int:
|
async def count_msg_by_bot_id(bot_id: str) -> int:
|
@@ -64,6 +64,8 @@ data
|
|||||||
- percent: float
|
- percent: float
|
||||||
- total: int
|
- total: int
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
||||||
# status_card_cache = {} # lang -> bytes
|
# status_card_cache = {} # lang -> bytes
|
||||||
|
|
||||||
|
|
||||||
@@ -90,11 +92,11 @@ data
|
|||||||
# 获取状态卡片
|
# 获取状态卡片
|
||||||
# bot_id 参数已经是bot参数的一部分了,不需要保留,但为了“兼容性”……
|
# bot_id 参数已经是bot参数的一部分了,不需要保留,但为了“兼容性”……
|
||||||
async def generate_status_card(
|
async def generate_status_card(
|
||||||
bot: dict,
|
bot: dict,
|
||||||
hardware: dict,
|
hardware: dict,
|
||||||
liteyuki: dict,
|
liteyuki: dict,
|
||||||
lang="zh-CN",
|
lang="zh-CN",
|
||||||
bot_id="0",
|
bot_id="0",
|
||||||
) -> bytes:
|
) -> bytes:
|
||||||
return await template2image(
|
return await template2image(
|
||||||
get_path("templates/status.html", abs_path=True),
|
get_path("templates/status.html", abs_path=True),
|
||||||
@@ -269,7 +271,9 @@ async def get_hardware_data() -> dict:
|
|||||||
for disk in psutil.disk_partitions(all=True):
|
for disk in psutil.disk_partitions(all=True):
|
||||||
try:
|
try:
|
||||||
disk_usage = psutil.disk_usage(disk.mountpoint)
|
disk_usage = psutil.disk_usage(disk.mountpoint)
|
||||||
if disk_usage.total == 0:
|
if disk_usage.total == 0 or disk.mountpoint.startswith(
|
||||||
|
("/var", "/boot", "/run", "/proc", "/sys", "/dev", "/tmp", "/snap")
|
||||||
|
):
|
||||||
continue # 虚拟磁盘
|
continue # 虚拟磁盘
|
||||||
result["disk"].append(
|
result["disk"].append(
|
||||||
{
|
{
|
||||||
@@ -297,7 +301,7 @@ async def get_liteyuki_data() -> dict:
|
|||||||
"python": f"{platform.python_implementation()} {platform.python_version()}",
|
"python": f"{platform.python_implementation()} {platform.python_version()}",
|
||||||
"system": f"{platform.system()} {platform.release()}",
|
"system": f"{platform.system()} {platform.release()}",
|
||||||
"runtime": time.time()
|
"runtime": time.time()
|
||||||
- temp_data.data.get("start_time", time.time()), # 运行时间秒数
|
- temp_data.data.get("start_time", time.time()), # 运行时间秒数
|
||||||
"bots": len(nonebot.get_bots()),
|
"bots": len(nonebot.get_bots()),
|
||||||
}
|
}
|
||||||
return result
|
return result
|
@@ -15,7 +15,7 @@ __plugin_meta__ = PluginMetadata(
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
from ...utils.base.data_manager import set_memory_data
|
from src.utils.base.data_manager import set_memory_data
|
||||||
|
|
||||||
driver = get_driver()
|
driver = get_driver()
|
||||||
|
|
@@ -3,8 +3,8 @@ import aiohttp
|
|||||||
from .qw_models import *
|
from .qw_models import *
|
||||||
import httpx
|
import httpx
|
||||||
|
|
||||||
from ...utils.base.data_manager import get_memory_data
|
from src.utils.base.data_manager import get_memory_data
|
||||||
from ...utils.base.language import Language
|
from src.utils.base.language import Language
|
||||||
|
|
||||||
dev_url = "https://devapi.qweather.com/" # 开发HBa
|
dev_url = "https://devapi.qweather.com/" # 开发HBa
|
||||||
com_url = "https://api.qweather.com/" # 正式环境
|
com_url = "https://api.qweather.com/" # 正式环境
|
||||||
@@ -24,8 +24,8 @@ def get_qw_lang(lang: str) -> str:
|
|||||||
async def check_key_dev(key: str) -> bool:
|
async def check_key_dev(key: str) -> bool:
|
||||||
url = "https://api.qweather.com/v7/weather/now?"
|
url = "https://api.qweather.com/v7/weather/now?"
|
||||||
params = {
|
params = {
|
||||||
"location": "101010100",
|
"location": "101010100",
|
||||||
"key" : key,
|
"key" : key,
|
||||||
}
|
}
|
||||||
async with aiohttp.ClientSession() as client:
|
async with aiohttp.ClientSession() as client:
|
||||||
resp = await client.get(url, params=params)
|
resp = await client.get(url, params=params)
|
||||||
@@ -43,27 +43,27 @@ def get_local_data(ulang_code: str) -> dict:
|
|||||||
"""
|
"""
|
||||||
ulang = Language(ulang_code)
|
ulang = Language(ulang_code)
|
||||||
return {
|
return {
|
||||||
"monday" : ulang.get("weather.monday"),
|
"monday" : ulang.get("weather.monday"),
|
||||||
"tuesday" : ulang.get("weather.tuesday"),
|
"tuesday" : ulang.get("weather.tuesday"),
|
||||||
"wednesday" : ulang.get("weather.wednesday"),
|
"wednesday" : ulang.get("weather.wednesday"),
|
||||||
"thursday" : ulang.get("weather.thursday"),
|
"thursday" : ulang.get("weather.thursday"),
|
||||||
"friday" : ulang.get("weather.friday"),
|
"friday" : ulang.get("weather.friday"),
|
||||||
"saturday" : ulang.get("weather.saturday"),
|
"saturday" : ulang.get("weather.saturday"),
|
||||||
"sunday" : ulang.get("weather.sunday"),
|
"sunday" : ulang.get("weather.sunday"),
|
||||||
"today" : ulang.get("weather.today"),
|
"today" : ulang.get("weather.today"),
|
||||||
"tomorrow" : ulang.get("weather.tomorrow"),
|
"tomorrow" : ulang.get("weather.tomorrow"),
|
||||||
"day" : ulang.get("weather.day"),
|
"day" : ulang.get("weather.day"),
|
||||||
"night" : ulang.get("weather.night"),
|
"night" : ulang.get("weather.night"),
|
||||||
"no_aqi" : ulang.get("weather.no_aqi"),
|
"no_aqi" : ulang.get("weather.no_aqi"),
|
||||||
"now-windVelocity" : ulang.get("weather.now-windVelocity"),
|
"now-windVelocity" : ulang.get("weather.now-windVelocity"),
|
||||||
"now-humidity" : ulang.get("weather.now-humidity"),
|
"now-humidity" : ulang.get("weather.now-humidity"),
|
||||||
"now-feelsLike" : ulang.get("weather.now-feelsLike"),
|
"now-feelsLike" : ulang.get("weather.now-feelsLike"),
|
||||||
"now-precip" : ulang.get("weather.now-precip"),
|
"now-precip" : ulang.get("weather.now-precip"),
|
||||||
"now-pressure" : ulang.get("weather.now-pressure"),
|
"now-pressure" : ulang.get("weather.now-pressure"),
|
||||||
"now-vis" : ulang.get("weather.now-vis"),
|
"now-vis" : ulang.get("weather.now-vis"),
|
||||||
"now-cloud" : ulang.get("weather.now-cloud"),
|
"now-cloud" : ulang.get("weather.now-cloud"),
|
||||||
"astronomy-sunrise" : ulang.get("weather.astronomy-sunrise"),
|
"astronomy-sunrise" : ulang.get("weather.astronomy-sunrise"),
|
||||||
"astronomy-sunset" : ulang.get("weather.astronomy-sunset"),
|
"astronomy-sunset" : ulang.get("weather.astronomy-sunset"),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -88,11 +88,11 @@ async def city_lookup(
|
|||||||
"""
|
"""
|
||||||
url = "https://geoapi.qweather.com/v2/city/lookup?"
|
url = "https://geoapi.qweather.com/v2/city/lookup?"
|
||||||
params = {
|
params = {
|
||||||
"location": location,
|
"location": location,
|
||||||
"adm" : adm,
|
"adm" : adm,
|
||||||
"number" : number,
|
"number" : number,
|
||||||
"key" : key,
|
"key" : key,
|
||||||
"lang" : lang,
|
"lang" : lang,
|
||||||
}
|
}
|
||||||
async with httpx.AsyncClient() as client:
|
async with httpx.AsyncClient() as client:
|
||||||
resp = await client.get(url, params=params)
|
resp = await client.get(url, params=params)
|
||||||
@@ -109,10 +109,10 @@ async def get_weather_now(
|
|||||||
url_path = "v7/weather/now?"
|
url_path = "v7/weather/now?"
|
||||||
url = dev_url + url_path if dev else com_url + url_path
|
url = dev_url + url_path if dev else com_url + url_path
|
||||||
params = {
|
params = {
|
||||||
"location": location,
|
"location": location,
|
||||||
"key" : key,
|
"key" : key,
|
||||||
"lang" : lang,
|
"lang" : lang,
|
||||||
"unit" : unit,
|
"unit" : unit,
|
||||||
}
|
}
|
||||||
async with httpx.AsyncClient() as client:
|
async with httpx.AsyncClient() as client:
|
||||||
resp = await client.get(url, params=params)
|
resp = await client.get(url, params=params)
|
||||||
@@ -129,10 +129,10 @@ async def get_weather_daily(
|
|||||||
url_path = "v7/weather/%dd?" % (7 if dev else 30)
|
url_path = "v7/weather/%dd?" % (7 if dev else 30)
|
||||||
url = dev_url + url_path if dev else com_url + url_path
|
url = dev_url + url_path if dev else com_url + url_path
|
||||||
params = {
|
params = {
|
||||||
"location": location,
|
"location": location,
|
||||||
"key" : key,
|
"key" : key,
|
||||||
"lang" : lang,
|
"lang" : lang,
|
||||||
"unit" : unit,
|
"unit" : unit,
|
||||||
}
|
}
|
||||||
async with httpx.AsyncClient() as client:
|
async with httpx.AsyncClient() as client:
|
||||||
resp = await client.get(url, params=params)
|
resp = await client.get(url, params=params)
|
||||||
@@ -149,10 +149,10 @@ async def get_weather_hourly(
|
|||||||
url_path = "v7/weather/%dh?" % (24 if dev else 168)
|
url_path = "v7/weather/%dh?" % (24 if dev else 168)
|
||||||
url = dev_url + url_path if dev else com_url + url_path
|
url = dev_url + url_path if dev else com_url + url_path
|
||||||
params = {
|
params = {
|
||||||
"location": location,
|
"location": location,
|
||||||
"key" : key,
|
"key" : key,
|
||||||
"lang" : lang,
|
"lang" : lang,
|
||||||
"unit" : unit,
|
"unit" : unit,
|
||||||
}
|
}
|
||||||
async with httpx.AsyncClient() as client:
|
async with httpx.AsyncClient() as client:
|
||||||
resp = await client.get(url, params=params)
|
resp = await client.get(url, params=params)
|
||||||
@@ -170,10 +170,10 @@ async def get_airquality(
|
|||||||
url_path = f"airquality/v1/now/{location}?"
|
url_path = f"airquality/v1/now/{location}?"
|
||||||
url = dev_url + url_path if dev else com_url + url_path
|
url = dev_url + url_path if dev else com_url + url_path
|
||||||
params = {
|
params = {
|
||||||
"key" : key,
|
"key" : key,
|
||||||
"lang" : lang,
|
"lang" : lang,
|
||||||
"pollutant": pollutant,
|
"pollutant": pollutant,
|
||||||
"station" : station,
|
"station" : station,
|
||||||
}
|
}
|
||||||
async with httpx.AsyncClient() as client:
|
async with httpx.AsyncClient() as client:
|
||||||
resp = await client.get(url, params=params)
|
resp = await client.get(url, params=params)
|
||||||
@@ -188,9 +188,9 @@ async def get_astronomy(
|
|||||||
url_path = f"v7/astronomy/sun?"
|
url_path = f"v7/astronomy/sun?"
|
||||||
url = dev_url + url_path if dev else com_url + url_path
|
url = dev_url + url_path if dev else com_url + url_path
|
||||||
params = {
|
params = {
|
||||||
"key" : key,
|
"key" : key,
|
||||||
"location" : location,
|
"location" : location,
|
||||||
"date" : date,
|
"date" : date,
|
||||||
}
|
}
|
||||||
async with httpx.AsyncClient() as client:
|
async with httpx.AsyncClient() as client:
|
||||||
resp = await client.get(url, params=params)
|
resp = await client.get(url, params=params)
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user