1
0
forked from bot/app

🔥 小型重构

This commit is contained in:
远野千束 2024-06-26 13:52:04 +08:00
parent 35823be13e
commit 8b01943d14
268 changed files with 25225 additions and 24996 deletions

2
.gitignore vendored
View File

@ -15,7 +15,7 @@ _config.yml
config.yml config.yml
config.example.yml config.example.yml
compile.bat compile.bat
liteyuki/resources/templates/latest-debug.html src/resources/templates/latest-debug.html
# vuepress # vuepress
.github .github
pyproject.toml pyproject.toml

View File

@ -1,6 +1,6 @@
import {defineClientConfig} from "vuepress/client"; import {defineClientConfig} from "vuepress/client";
import resourceStoreComp from "./components/res_store.vue"; import resourceStoreComp from "./components/ResStore.vue";
import pluginStoreComp from "./components/plugin_store.vue"; import pluginStoreComp from "./components/PluginStore.vue";
//导入element-plus //导入element-plus
import ElementPlus from 'element-plus'; import ElementPlus from 'element-plus';
@ -9,6 +9,5 @@ export default defineClientConfig({
app.component("resourceStoreComp", resourceStoreComp); app.component("resourceStoreComp", resourceStoreComp);
app.component("pluginStoreComp", pluginStoreComp); app.component("pluginStoreComp", pluginStoreComp);
app.use(ElementPlus); app.use(ElementPlus);
}, },
}); });

View File

@ -1,6 +1,6 @@
<script setup lang="ts"> <script setup lang="ts">
import {ref} from 'vue' import {ref} from 'vue'
import ItemCard from './plugin_item_card.vue' import ItemCard from './PluginItemCard.vue'
// Nonebot // Nonebot
let items = ref([]) let items = ref([])

View File

@ -1,10 +1,10 @@
<script setup lang="ts"> <script setup lang="ts">
import {ref} from 'vue' import {ref} from 'vue'
import ItemCard from './res_item_card.vue' import ItemCard from './ResItemCard.vue'
// public/assets/resources.json // public/assets/resources.json
let items = ref([]) let items = ref([])
fetch('https://bot.liteyuki.icu/assets/resources.json') fetch('/assets/resources.json')
.then(response => response.json()) .then(response => response.json())
.then(data => { .then(data => {
items.value = data items.value = data

View File

@ -10,6 +10,7 @@ export default defineUserConfig({
description: "LiteyukiBot | 轻雪机器人 | An OneBot Standard ChatBot | 一个OneBot标准的聊天机器人", description: "LiteyukiBot | 轻雪机器人 | An OneBot Standard ChatBot | 一个OneBot标准的聊天机器人",
head: [ head: [
// 设置 favor.ico.vuepress/public 下 // 设置 favor.ico.vuepress/public 下
["script", {src: "/js/style.js", "type": "module"}],
['link', {rel: 'icon', href: 'https://cdn.liteyuki.icu/favicon.ico'},], ['link', {rel: 'icon', href: 'https://cdn.liteyuki.icu/favicon.ico'},],
['link', {rel: 'stylesheet', href: 'https://cdn.bootcdn.net/ajax/libs/firacode/6.2.0/fira_code.min.css'}], ['link', {rel: 'stylesheet', href: 'https://cdn.bootcdn.net/ajax/libs/firacode/6.2.0/fira_code.min.css'}],

View File

@ -0,0 +1,22 @@
function applyStyle() {
let lineNumbers = document.body.querySelectorAll('[class^="language-"].line-numbers-mode')
lineNumbers.forEach((item) => {
// 插入现成的html文本
let title = item.getAttribute('data-title')
let tabStr =
"<div class='tab' style='display: flex; background-color: #d0e9ff'>" +
" <div class='tab-buttons'>" +
" <div class='tab-button' style='background-color: #FF5F57'></div>" +
" <div class='tab-button' style='background-color: #FFBD2E'></div>" +
" <div class='tab-button' style='background-color: #27C93F'></div>" +
" </div>" +
` <div class='tab-title'>${title}</div>` +
" <div style='flex: 1'></div>" +
"</div>"
// 在代码块前插入选项卡
item.insertAdjacentHTML('beforebegin', tabStr);
})
}
applyStyle()

View File

@ -1,5 +1,10 @@
// place your custom styles here // place your custom styles here
:root {
--code-window-border-radius: 10px;
--button-distance: 8px;
}
#main-title { #main-title {
font-family: ColorTube, "Fira Code", serif; font-family: ColorTube, "Fira Code", serif;
color: #ff0000 !important; /* 你想要的颜色 */ color: #ff0000 !important; /* 你想要的颜色 */
@ -23,3 +28,54 @@ code {
#main-title { #main-title {
display: none; display: none;
} }
.theme-hope-content pre {
overflow: auto;
margin: 0 0;
padding: 1rem;
border-radius: 6px;
line-height: 1.375;
}
// 移除该before
.theme-hope-content pre::before {
content: none;
}
.theme-hope-content > div[class*=language-] {
margin: 0 0 0 0;
// 仅下半部分有圆弧
border-radius: 0 0 var(--code-window-border-radius) var(--code-window-border-radius);
}
.tab {
display: flex;
height: 25px;
margin-bottom: 0;
justify-content: space-between;
align-items: center;
border-top-left-radius: var(--code-window-border-radius);
border-top-right-radius: var(--code-window-border-radius);
}
.tab-buttons {
padding: 7px;
flex: 1;
display: flex;
justify-content: flex-start;
height: 60%;
align-items: center;
}
.tab-button {
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
margin-right: var(--button-distance);
border-radius: 50%;
height: 100%;
aspect-ratio: 1/1;
}
.tab-title{
text-align: center;
justify-content: center;
flex: 1;
}

View File

@ -21,6 +21,7 @@
"dependencies": { "dependencies": {
"clipboard": "^2.0.11", "clipboard": "^2.0.11",
"element-plus": "^2.7.0", "element-plus": "^2.7.0",
"element-ui": "^2.15.14" "element-ui": "^2.15.14",
"vue-router": "^4.4.0"
} }
} }

View File

@ -14,6 +14,9 @@ dependencies:
element-ui: element-ui:
specifier: ^2.15.14 specifier: ^2.15.14
version: 2.15.14(vue@3.4.21) version: 2.15.14(vue@3.4.21)
vue-router:
specifier: ^4.4.0
version: 4.4.0(vue@3.4.21)
devDependencies: devDependencies:
'@vuepress/bundler-vite': '@vuepress/bundler-vite':
@ -938,7 +941,6 @@ packages:
/@vue/devtools-api@6.6.1: /@vue/devtools-api@6.6.1:
resolution: {integrity: sha512-LgPscpE3Vs0x96PzSSB4IGVSZXZBZHpfxs+ZA1d+VEPwHdOXowy/Y2CsvCAIFrf+ssVU1pD1jidj505EpUnfbA==} resolution: {integrity: sha512-LgPscpE3Vs0x96PzSSB4IGVSZXZBZHpfxs+ZA1d+VEPwHdOXowy/Y2CsvCAIFrf+ssVU1pD1jidj505EpUnfbA==}
dev: true
/@vue/reactivity@3.4.21: /@vue/reactivity@3.4.21:
resolution: {integrity: sha512-UhenImdc0L0/4ahGCyEzc/pZNwVgcglGy9HVzJ1Bq2Mm9qXOpP8RyNTjookw/gOCUlXSEtuZ2fUg5nrHcoqJcw==} resolution: {integrity: sha512-UhenImdc0L0/4ahGCyEzc/pZNwVgcglGy9HVzJ1Bq2Mm9qXOpP8RyNTjookw/gOCUlXSEtuZ2fUg5nrHcoqJcw==}
@ -985,7 +987,7 @@ packages:
rollup: 4.13.1 rollup: 4.13.1
vite: 5.2.6 vite: 5.2.6
vue: 3.4.21 vue: 3.4.21
vue-router: 4.3.0(vue@3.4.21) vue-router: 4.4.0(vue@3.4.21)
transitivePeerDependencies: transitivePeerDependencies:
- '@types/node' - '@types/node'
- jiti - jiti
@ -1021,7 +1023,7 @@ packages:
'@vue/devtools-api': 6.6.1 '@vue/devtools-api': 6.6.1
'@vuepress/shared': 2.0.0-rc.9 '@vuepress/shared': 2.0.0-rc.9
vue: 3.4.21 vue: 3.4.21
vue-router: 4.3.0(vue@3.4.21) vue-router: 4.4.0(vue@3.4.21)
transitivePeerDependencies: transitivePeerDependencies:
- typescript - typescript
dev: true dev: true
@ -2739,14 +2741,13 @@ packages:
dependencies: dependencies:
vue: 3.4.21 vue: 3.4.21
/vue-router@4.3.0(vue@3.4.21): /vue-router@4.4.0(vue@3.4.21):
resolution: {integrity: sha512-dqUcs8tUeG+ssgWhcPbjHvazML16Oga5w34uCUmsk7i0BcnskoLGwjpa15fqMr2Fa5JgVBrdL2MEgqz6XZ/6IQ==} resolution: {integrity: sha512-HB+t2p611aIZraV2aPSRNXf0Z/oLZFrlygJm+sZbdJaW6lcFqEDQwnzUBXn+DApw+/QzDU/I9TeWx9izEjTmsA==}
peerDependencies: peerDependencies:
vue: ^3.2.0 vue: ^3.2.0
dependencies: dependencies:
'@vue/devtools-api': 6.6.1 '@vue/devtools-api': 6.6.1
vue: 3.4.21 vue: 3.4.21
dev: true
/vue@3.4.21: /vue@3.4.21:
resolution: {integrity: sha512-5hjyV/jLEIKD/jYl4cavMcnzKwjMKohureP8ejn3hhEjwhWIhWeuzL2kJAjzl/WyVsgPY56Sy4Z40C3lVshxXA==} resolution: {integrity: sha512-5hjyV/jLEIKD/jYl4cavMcnzKwjMKohureP8ejn3hhEjwhWIhWeuzL2kJAjzl/WyVsgPY56Sy4Z40C3lVshxXA==}

12
main.py
View File

@ -1,8 +1,8 @@
import nonebot import nonebot
from liteyuki.utils import adapter_manager, driver_manager, init from src.utils import adapter_manager, driver_manager, init
from liteyuki.utils.base.config import load_from_yaml from src.utils.base.config import load_from_yaml
from liteyuki.utils.base.data_manager import StoredConfig, common_db from src.utils.base.data_manager import StoredConfig, common_db
from liteyuki.utils.base.ly_api import liteyuki_api from src.utils.base.ly_api import liteyuki_api
if __name__ == "__mp_main__": if __name__ == "__mp_main__":
# Start as multiprocessing # Start as multiprocessing
@ -15,7 +15,7 @@ if __name__ == "__mp_main__":
nonebot.init(**store_config) nonebot.init(**store_config)
adapter_manager.register() adapter_manager.register()
try: try:
nonebot.load_plugin("liteyuki.liteyuki_main") nonebot.load_plugin("src.liteyuki_main")
nonebot.load_from_toml("pyproject.toml") nonebot.load_from_toml("pyproject.toml")
except BaseException as e: except BaseException as e:
if not isinstance(e, KeyboardInterrupt): if not isinstance(e, KeyboardInterrupt):
@ -24,6 +24,6 @@ if __name__ == "__mp_main__":
if __name__ == "__main__": if __name__ == "__main__":
# Start as __main__ # Start as __main__
from liteyuki.utils.base.reloader import Reloader from src.utils.base.reloader import Reloader
nonebot.run() nonebot.run()

View File

@ -10,6 +10,7 @@ nonebot-adapter-onebot~=2.4.3
nonebot-plugin-alconna~=0.46.3 nonebot-plugin-alconna~=0.46.3
nonebot_plugin_apscheduler~=0.4.0 nonebot_plugin_apscheduler~=0.4.0
nonebot-adapter-satori~=0.11.5 nonebot-adapter-satori~=0.11.5
numpy~=2.0.0
packaging~=23.1 packaging~=23.1
psutil~=5.9.8 psutil~=5.9.8
py-cpuinfo~=9.0.0 py-cpuinfo~=9.0.0

View File

@ -0,0 +1,6 @@
import abc
class Bot(abc.ABC):
def __init__(self):
pass

10
src/liteyuki/exception.py Normal file
View File

@ -0,0 +1,10 @@
"""exception模块包含了liteyuki运行中的所有错误
"""
from typing import Any, Optional
class LiteyukiException(BaseException):
"""Liteyuki的异常基类。"""
def __str__(self) -> str:
return self.__repr__()

View File

@ -1,7 +1,7 @@
import nonebot import nonebot
from git import Repo from git import Repo
from liteyuki.utils.base.config import get_config from src.utils.base.config import get_config
remote_urls = [ remote_urls = [
"https://github.com/snowykami/LiteyukiBot.git", "https://github.com/snowykami/LiteyukiBot.git",

View File

@ -11,13 +11,13 @@ from nonebot.exception import MockApiException
from nonebot.internal.matcher import Matcher from nonebot.internal.matcher import Matcher
from nonebot.permission import SUPERUSER from nonebot.permission import SUPERUSER
from liteyuki.utils.base.config import get_config, load_from_yaml from src.utils.base.config import get_config, load_from_yaml
from liteyuki.utils.base.data_manager import StoredConfig, TempConfig, common_db from src.utils.base.data_manager import StoredConfig, TempConfig, common_db
from liteyuki.utils.base.language import get_user_lang from src.utils.base.language import get_user_lang
from liteyuki.utils.base.ly_typing import T_Bot, T_MessageEvent from src.utils.base.ly_typing import T_Bot, T_MessageEvent
from liteyuki.utils.message.message import MarkdownMessage as md, broadcast_to_superusers from src.utils.message.message import MarkdownMessage as md, broadcast_to_superusers
from liteyuki.utils.base.reloader import Reloader from src.utils.base.reloader import Reloader
from liteyuki.utils import event as event_utils, satori_utils from src.utils import event as event_utils, satori_utils
from .api import update_liteyuki from .api import update_liteyuki
from ..utils.base.ly_function import get_function from ..utils.base.ly_function import get_function

View File

@ -2,34 +2,37 @@ import nonebot
from watchdog.observers import Observer from watchdog.observers import Observer
from watchdog.events import FileSystemEventHandler from watchdog.events import FileSystemEventHandler
from liteyuki.utils.base.config import get_config from src.utils.base.config import get_config
from liteyuki.utils.base.reloader import Reloader from src.utils.base.reloader import Reloader
from liteyuki.utils.base.resource import load_resources from src.utils.base.resource import load_resources
if get_config("debug", False): if get_config("debug", False):
src_directories = ( src_directories = (
"liteyuki/liteyuki_main", "src/liteyuki_main",
"liteyuki/plugins", "src/plugins",
"liteyuki/utils", "src/utils",
) )
src_excludes_extensions = ( src_excludes_extensions = (
"pyc", "pyc",
) )
res_directories = ( res_directories = (
"liteyuki/resources", "src/resources",
"resources", "resources",
) )
nonebot.logger.info("Liteyuki Reload is enable, watching for file changes...") nonebot.logger.info("Liteyuki Reload is enable, watching for file changes...")
class CodeModifiedHandler(FileSystemEventHandler): class CodeModifiedHandler(FileSystemEventHandler):
""" """
Handler for code file changes Handler for code file changes
""" """
def on_modified(self, event): def on_modified(self, event):
if event.src_path.endswith(src_excludes_extensions) or event.is_directory or "__pycache__" in event.src_path: if event.src_path.endswith(
src_excludes_extensions) or event.is_directory or "__pycache__" in event.src_path:
return return
nonebot.logger.info(f"{event.src_path} modified, reloading bot...") nonebot.logger.info(f"{event.src_path} modified, reloading bot...")
Reloader.reload() Reloader.reload()
@ -39,6 +42,7 @@ if get_config("debug", False):
""" """
Handler for resource file changes Handler for resource file changes
""" """
def on_modified(self, event): def on_modified(self, event):
nonebot.logger.info(f"{event.src_path} modified, reloading resource...") nonebot.logger.info(f"{event.src_path} modified, reloading resource...")
load_resources() load_resources()

View File

@ -1,10 +1,10 @@
import nonebot.plugin import nonebot.plugin
from nonebot import get_driver from nonebot import get_driver
from liteyuki.utils import init_log from src.utils import init_log
from liteyuki.utils.base.config import get_config from src.utils.base.config import get_config
from liteyuki.utils.base.data_manager import InstalledPlugin, plugin_db from src.utils.base.data_manager import InstalledPlugin, plugin_db
from liteyuki.utils.base.resource import load_resources from src.utils.base.resource import load_resources
from liteyuki.utils.message.tools import check_for_package from src.utils.message.tools import check_for_package
load_resources() load_resources()
init_log() init_log()

View File

@ -3,11 +3,11 @@ from urllib.parse import quote
import aiohttp import aiohttp
from nonebot import require from nonebot import require
from liteyuki.utils.event import get_user_id from src.utils.event import get_user_id
from liteyuki.utils.base.language import Language from src.utils.base.language import Language
from liteyuki.utils.base.ly_typing import T_MessageEvent from src.utils.base.ly_typing import T_MessageEvent
from liteyuki.utils.base.resource import get_path from src.utils.base.resource import get_path
from liteyuki.utils.message.html_tool import template2image from src.utils.message.html_tool import template2image
require("nonebot_plugin_alconna") require("nonebot_plugin_alconna")

View File

@ -2,9 +2,9 @@ import nonebot
from nonebot import on_message, require from nonebot import on_message, require
from nonebot.plugin import PluginMetadata from nonebot.plugin import PluginMetadata
from liteyuki.utils.base.data import Database, LiteModel from src.utils.base.data import Database, LiteModel
from liteyuki.utils.base.ly_typing import T_Bot, T_MessageEvent from src.utils.base.ly_typing import T_Bot, T_MessageEvent
from liteyuki.utils.message.message import MarkdownMessage as md from src.utils.message.message import MarkdownMessage as md
require("nonebot_plugin_alconna") require("nonebot_plugin_alconna")
from nonebot_plugin_alconna import on_alconna from nonebot_plugin_alconna import on_alconna

View File

@ -4,9 +4,9 @@ from nonebot.params import CommandArg
from nonebot.permission import SUPERUSER from nonebot.permission import SUPERUSER
from nonebot.plugin import PluginMetadata from nonebot.plugin import PluginMetadata
from liteyuki.utils.base.ly_typing import T_Bot, T_MessageEvent, v11 from src.utils.base.ly_typing import T_Bot, T_MessageEvent, v11
from liteyuki.utils.message.message import MarkdownMessage as md, broadcast_to_superusers from src.utils.message.message import MarkdownMessage as md, broadcast_to_superusers
from liteyuki.utils.message.html_tool import * from src.utils.message.html_tool import *
md_test = on_command("mdts", permission=SUPERUSER) md_test = on_command("mdts", permission=SUPERUSER)
btn_test = on_command("btnts", permission=SUPERUSER) btn_test = on_command("btnts", permission=SUPERUSER)

View File

@ -1,6 +1,6 @@
import random import random
from pydantic import BaseModel from pydantic import BaseModel
from liteyuki.utils.message.message import MarkdownMessage as md from src.utils.message.message import MarkdownMessage as md
class Dot(BaseModel): class Dot(BaseModel):
row: int row: int

View File

@ -1,7 +1,7 @@
from nonebot import require from nonebot import require
from liteyuki.utils.base.ly_typing import T_Bot, T_MessageEvent from src.utils.base.ly_typing import T_Bot, T_MessageEvent
from liteyuki.utils.message.message import MarkdownMessage as md from src.utils.message.message import MarkdownMessage as md
require("nonebot_plugin_alconna") require("nonebot_plugin_alconna")
from .game import Minesweeper from .game import Minesweeper

View File

@ -5,10 +5,10 @@ import aiofiles
import nonebot.plugin import nonebot.plugin
from nonebot.adapters import satori from nonebot.adapters import satori
from liteyuki.utils import event as event_utils from src.utils import event as event_utils
from liteyuki.utils.base.data import LiteModel from src.utils.base.data import LiteModel
from liteyuki.utils.base.data_manager import GlobalPlugin, Group, User, group_db, plugin_db, user_db from src.utils.base.data_manager import GlobalPlugin, Group, User, group_db, plugin_db, user_db
from liteyuki.utils.base.ly_typing import T_MessageEvent from src.utils.base.ly_typing import T_MessageEvent
__group_data = {} # 群数据缓存, {group_id: Group} __group_data = {} # 群数据缓存, {group_id: Group}
__user_data = {} # 用户数据缓存, {user_id: User} __user_data = {} # 用户数据缓存, {user_id: User}

View File

@ -14,13 +14,13 @@ from nonebot.permission import SUPERUSER
from nonebot.plugin import Plugin, PluginMetadata from nonebot.plugin import Plugin, PluginMetadata
from nonebot.utils import run_sync from nonebot.utils import run_sync
from liteyuki.utils.base.data_manager import InstalledPlugin from src.utils.base.data_manager import InstalledPlugin
from liteyuki.utils.base.language import get_user_lang from src.utils.base.language import get_user_lang
from liteyuki.utils.base.ly_typing import T_Bot from src.utils.base.ly_typing import T_Bot
from liteyuki.utils.message.message import MarkdownMessage as md from src.utils.message.message import MarkdownMessage as md
from liteyuki.utils.message.markdown import MarkdownComponent as mdc, compile_md, escape_md from src.utils.message.markdown import MarkdownComponent as mdc, compile_md, escape_md
from liteyuki.utils.base.permission import GROUP_ADMIN, GROUP_OWNER from src.utils.base.permission import GROUP_ADMIN, GROUP_OWNER
from liteyuki.utils.message.tools import clamp from src.utils.message.tools import clamp
from .common import * from .common import *
require("nonebot_plugin_alconna") require("nonebot_plugin_alconna")

View File

@ -6,10 +6,10 @@ from nonebot import require
from nonebot.internal.matcher import Matcher from nonebot.internal.matcher import Matcher
from nonebot.permission import SUPERUSER from nonebot.permission import SUPERUSER
from liteyuki.utils.base.language import get_user_lang from src.utils.base.language import get_user_lang
from liteyuki.utils.base.ly_typing import T_Bot, T_MessageEvent from src.utils.base.ly_typing import T_Bot, T_MessageEvent
from liteyuki.utils.message.message import MarkdownMessage as md from src.utils.message.message import MarkdownMessage as md
from liteyuki.utils.base.resource import (ResourceMetadata, add_resource_pack, change_priority, check_exist, check_status, get_loaded_resource_packs, get_resource_metadata, load_resources, remove_resource_pack) from src.utils.base.resource import (ResourceMetadata, add_resource_pack, change_priority, check_exist, check_status, get_loaded_resource_packs, get_resource_metadata, load_resources, remove_resource_pack)
require("nonebot_plugin_alconna") require("nonebot_plugin_alconna")
from nonebot_plugin_alconna import Alconna, Args, on_alconna, Arparma, Subcommand from nonebot_plugin_alconna import Alconna, Args, on_alconna, Arparma, Subcommand

View File

@ -2,11 +2,11 @@ import nonebot
from nonebot.message import event_preprocessor from nonebot.message import event_preprocessor
# from nonebot_plugin_alconna.typings import Event # from nonebot_plugin_alconna.typings import Event
from liteyuki.utils.base.ly_typing import T_MessageEvent from src.utils.base.ly_typing import T_MessageEvent
from liteyuki.utils import satori_utils from src.utils import satori_utils
from nonebot.adapters import satori from nonebot.adapters import satori
from nonebot_plugin_alconna.typings import Event from nonebot_plugin_alconna.typings import Event
from liteyuki.plugins.liteyuki_status.counter_for_satori import satori_counter from src.plugins.liteyuki_status.counter_for_satori import satori_counter
@event_preprocessor @event_preprocessor

View File

@ -5,10 +5,10 @@ import aiohttp
from nonebot import require from nonebot import require
from nonebot.plugin import PluginMetadata from nonebot.plugin import PluginMetadata
from liteyuki.utils.base.config import get_config from src.utils.base.config import get_config
from liteyuki.utils.base.data import Database, LiteModel from src.utils.base.data import Database, LiteModel
from liteyuki.utils.base.resource import get_path from src.utils.base.resource import get_path
from liteyuki.utils.message.html_tool import template2image from src.utils.message.html_tool import template2image
require("nonebot_plugin_alconna") require("nonebot_plugin_alconna")
require("nonebot_plugin_apscheduler") require("nonebot_plugin_apscheduler")

View File

@ -8,12 +8,12 @@ from nonebot.permission import SUPERUSER
from nonebot.rule import to_me from nonebot.rule import to_me
from nonebot.typing import T_State from nonebot.typing import T_State
from liteyuki.utils.base.ly_typing import T_MessageEvent from src.utils.base.ly_typing import T_MessageEvent
from .utils import get_keywords from .utils import get_keywords
from liteyuki.utils.base.word_bank import get_reply from src.utils.base.word_bank import get_reply
from liteyuki.utils.event import get_message_type from src.utils.event import get_message_type
from liteyuki.utils.base.permission import GROUP_ADMIN, GROUP_OWNER from src.utils.base.permission import GROUP_ADMIN, GROUP_OWNER
from liteyuki.utils.base.data_manager import group_db, Group from src.utils.base.data_manager import group_db, Group
require("nonebot_plugin_alconna") require("nonebot_plugin_alconna")
from nonebot_plugin_alconna import on_alconna, Alconna, Args, Arparma from nonebot_plugin_alconna import on_alconna, Alconna, Args, Arparma

View File

@ -1,4 +1,4 @@
from liteyuki.utils.base.data import Database, LiteModel from src.utils.base.data import Database, LiteModel
class MessageEventModel(LiteModel): class MessageEventModel(LiteModel):

View File

@ -5,11 +5,11 @@ from collections import Counter
from nonebot import Bot from nonebot import Bot
from liteyuki.utils.message.html_tool import template2image from src.utils.message.html_tool import template2image
from .common import MessageEventModel, msg_db from .common import MessageEventModel, msg_db
from liteyuki.utils.base.language import Language from src.utils.base.language import Language
from liteyuki.utils.base.resource import get_path from src.utils.base.resource import get_path
from liteyuki.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 ...utils.external.logo import get_group_icon, get_user_icon

View File

@ -1,9 +1,9 @@
from nonebot import Bot, require from nonebot import Bot, require
from liteyuki.utils.message.string_tool import convert_duration, convert_time_to_seconds from src.utils.message.string_tool import convert_duration, convert_time_to_seconds
from .stat_api import * from .data_source import *
from liteyuki.utils import event as event_utils from src.utils import event as event_utils
from liteyuki.utils.base.language import Language from src.utils.base.language import Language
from liteyuki.utils.base.ly_typing import T_MessageEvent from src.utils.base.ly_typing import T_MessageEvent
require("nonebot_plugin_alconna") require("nonebot_plugin_alconna")

View File

@ -3,13 +3,13 @@ import time
from nonebot import require from nonebot import require
from nonebot.message import event_postprocessor from nonebot.message import event_postprocessor
from liteyuki.utils.base.data import Database, LiteModel from src.utils.base.data import Database, LiteModel
from liteyuki.utils.base.ly_typing import v11, v12, satori from src.utils.base.ly_typing import v11, v12, satori
from liteyuki.utils.base.ly_typing import T_Bot, T_MessageEvent from src.utils.base.ly_typing import T_Bot, T_MessageEvent
from .common import MessageEventModel, msg_db from .common import MessageEventModel, msg_db
from liteyuki.utils import event as event_utils from src.utils import event as event_utils
require("nonebot_plugin_alconna") require("nonebot_plugin_alconna")

View File

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2022 hemengyang
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@ -0,0 +1,107 @@
import asyncio
import concurrent.futures
import contextlib
import re
from functools import partial
from io import BytesIO
from random import choice
from typing import Optional
import jieba
import jieba.analyse
import numpy as np
from emoji import replace_emoji
from PIL import Image
from wordcloud import WordCloud
from .config import global_config, plugin_config
def pre_precess(msg: str) -> str:
"""对消息进行预处理"""
# 去除网址
# https://stackoverflow.com/a/17773849/9212748
url_regex = re.compile(
r"(https?:\/\/(?:www\.|(?!www))[a-zA-Z0-9][a-zA-Z0-9-]+[a-zA-Z0-9]\.[^\s]{2,}|www\.[a-zA-Z0-9][a-zA-Z0-9-]"
r"+[a-zA-Z0-9]\.[^\s]{2,}|https?:\/\/(?:www\.|(?!www))[a-zA-Z0-9]+\.[^\s]{2,}|www\.[a-zA-Z0-9]+\.[^\s]{2,})"
)
msg = url_regex.sub("", msg)
# 去除 \u200b
msg = re.sub(r"\u200b", "", msg)
# 去除 emoji
# https://github.com/carpedm20/emoji
msg = replace_emoji(msg)
return msg
def analyse_message(msg: str) -> dict[str, float]:
"""分析消息
分词并统计词频
"""
# 设置停用词表
if plugin_config.wordcloud_stopwords_path:
jieba.analyse.set_stop_words(plugin_config.wordcloud_stopwords_path)
# 加载用户词典
if plugin_config.wordcloud_userdict_path:
jieba.load_userdict(str(plugin_config.wordcloud_userdict_path))
# 基于 TF-IDF 算法的关键词抽取
# 返回所有关键词,因为设置了数量其实也只是 tags[:topK],不如交给词云库处理
words = jieba.analyse.extract_tags(msg, topK=0, withWeight=True)
return dict(words)
def get_mask(key: str):
"""获取 mask"""
mask_path = plugin_config.get_mask_path(key)
if mask_path.exists():
return np.array(Image.open(mask_path))
# 如果指定 mask 文件不存在,则尝试默认 mask
default_mask_path = plugin_config.get_mask_path()
if default_mask_path.exists():
return np.array(Image.open(default_mask_path))
def _get_wordcloud(messages: list[str], mask_key: str) -> Optional[bytes]:
# 过滤掉命令
command_start = tuple(i for i in global_config.command_start if i)
message = " ".join(m for m in messages if not m.startswith(command_start))
# 预处理
message = pre_precess(message)
# 分析消息。分词,并统计词频
frequency = analyse_message(message)
# 词云参数
wordcloud_options = {}
wordcloud_options.update(plugin_config.wordcloud_options)
wordcloud_options.setdefault("font_path", str(plugin_config.wordcloud_font_path))
wordcloud_options.setdefault("width", plugin_config.wordcloud_width)
wordcloud_options.setdefault("height", plugin_config.wordcloud_height)
wordcloud_options.setdefault(
"background_color", plugin_config.wordcloud_background_color
)
# 如果 colormap 是列表,则随机选择一个
colormap = (
plugin_config.wordcloud_colormap
if isinstance(plugin_config.wordcloud_colormap, str)
else choice(plugin_config.wordcloud_colormap)
)
wordcloud_options.setdefault("colormap", colormap)
wordcloud_options.setdefault("mask", get_mask(mask_key))
with contextlib.suppress(ValueError):
wordcloud = WordCloud(**wordcloud_options)
image = wordcloud.generate_from_frequencies(frequency).to_image()
image_bytes = BytesIO()
image.save(image_bytes, format="PNG")
return image_bytes.getvalue()
async def get_wordcloud(messages: list[str], mask_key: str) -> Optional[bytes]:
loop = asyncio.get_running_loop()
pfunc = partial(_get_wordcloud, messages, mask_key)
# 虽然不知道具体是哪里泄漏了,但是通过每次关闭线程池可以避免这个问题
# https://github.com/he0119/nonebot-plugin-wordcloud/issues/99
with concurrent.futures.ThreadPoolExecutor() as pool:
return await loop.run_in_executor(pool, pfunc)

View File

@ -7,13 +7,13 @@ from cpuinfo import cpuinfo
from nonebot import require from nonebot import require
from nonebot.adapters import satori from nonebot.adapters import satori
from liteyuki.utils import __NAME__, __VERSION__ from src.utils import __NAME__, __VERSION__
from liteyuki.utils.base.config import get_config from src.utils.base.config import get_config
from liteyuki.utils.base.data_manager import TempConfig, common_db from src.utils.base.data_manager import TempConfig, common_db
from liteyuki.utils.base.language import Language from src.utils.base.language import Language
from liteyuki.utils.base.resource import get_loaded_resource_packs, get_path from src.utils.base.resource import get_loaded_resource_packs, get_path
from liteyuki.utils.message.html_tool import template2image from src.utils.message.html_tool import template2image
from liteyuki.utils import satori_utils from src.utils import satori_utils
from .counter_for_satori import satori_counter from .counter_for_satori import satori_counter
from git import Repo from git import Repo

View File

@ -1,6 +1,6 @@
from liteyuki.utils import event as event_utils from src.utils import event as event_utils
from liteyuki.utils.base.language import get_user_lang from src.utils.base.language import get_user_lang
from liteyuki.utils.base.ly_typing import T_Bot, T_MessageEvent from src.utils.base.ly_typing import T_Bot, T_MessageEvent
from .api import * from .api import *
require("nonebot_plugin_alconna") require("nonebot_plugin_alconna")

View File

@ -3,13 +3,13 @@ from typing import Optional
import pytz import pytz
from nonebot import require from nonebot import require
from liteyuki.utils.base.data import LiteModel, Database from src.utils.base.data import LiteModel, Database
from liteyuki.utils.base.data_manager import User, user_db, group_db from src.utils.base.data_manager import User, user_db, group_db
from liteyuki.utils.base.language import Language, change_user_lang, get_all_lang, get_user_lang from src.utils.base.language import Language, change_user_lang, get_all_lang, get_user_lang
from liteyuki.utils.base.ly_typing import T_Bot, T_MessageEvent from src.utils.base.ly_typing import T_Bot, T_MessageEvent
from liteyuki.utils.message.message import MarkdownMessage as md from src.utils.message.message import MarkdownMessage as md
from .const import representative_timezones_list from .const import representative_timezones_list
from liteyuki.utils import event as event_utils from src.utils import event as event_utils
require("nonebot_plugin_alconna") require("nonebot_plugin_alconna")
from nonebot_plugin_alconna import Alconna, Args, Arparma, Subcommand, on_alconna from nonebot_plugin_alconna import Alconna, Args, Arparma, Subcommand, on_alconna

View File

@ -1,4 +1,4 @@
from liteyuki.utils.base.data import LiteModel from src.utils.base.data import LiteModel
class Location(LiteModel): class Location(LiteModel):

View File

@ -3,15 +3,15 @@ from nonebot.adapters import satori
from nonebot.adapters.onebot.v11 import MessageSegment from nonebot.adapters.onebot.v11 import MessageSegment
from nonebot.internal.matcher import Matcher from nonebot.internal.matcher import Matcher
from liteyuki.utils.base.config import get_config from src.utils.base.config import get_config
from liteyuki.utils.base.ly_typing import T_MessageEvent from src.utils.base.ly_typing import T_MessageEvent
from .qw_api import * from .qw_api import *
from liteyuki.utils.base.data_manager import User, user_db from src.utils.base.data_manager import User, user_db
from liteyuki.utils.base.language import Language, get_user_lang from src.utils.base.language import Language, get_user_lang
from liteyuki.utils.base.resource import get_path from src.utils.base.resource import get_path
from liteyuki.utils.message.html_tool import template2image from src.utils.message.html_tool import template2image
from liteyuki.utils import event as event_utils from src.utils import event as event_utils
require("nonebot_plugin_alconna") require("nonebot_plugin_alconna")
from nonebot_plugin_alconna import on_alconna, Alconna, Args, MultiVar, Arparma, UniMessage from nonebot_plugin_alconna import on_alconna, Alconna, Args, MultiVar, Arparma, UniMessage

Some files were not shown because too many files have changed in this diff Show More