From 1ad87e666ff98bd76056578e6c80f13f55152df1 Mon Sep 17 00:00:00 2001 From: ictye Date: Tue, 20 Aug 2024 02:45:39 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E8=A7=84=E8=8C=83=E6=8F=92=E4=BB=B6?= =?UTF-8?q?=E8=A1=8C=E4=B8=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 14 ++---- .../src/ictye_live_dm/GUI/Ui_MainWindow.py | 48 ++++++++++--------- ictye-live-dm/src/ictye_live_dm/GUI_main.py | 13 +++-- .../src/ictye_live_dm/QT-GUI/main.ui | 24 +++++++--- .../ictye_live_dm/depends/config_registrar.py | 9 ++-- .../src/ictye_live_dm/depends/pluginmain.py | 35 ++++++++++++-- .../src/ictye_live_dm/http_server.py | 3 +- .../src/ictye_live_dm/pluginsystem.py | 12 ++++- ictye-live-dm/tests/Config_schema_test.py | 2 +- 9 files changed, 105 insertions(+), 55 deletions(-) diff --git a/README.md b/README.md index bd85772..780d11a 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,8 @@
- - +

Ictye Live Danmku(ictye-live-dm)

- - - - + +
一个简单而又全能的弹幕姬框架(其实就是一个web服务器加上websocket服务器),通过插件来实现弹幕功能 @@ -16,7 +13,6 @@ 3. 如果是Windows用户则可以直接运行其中的启动脚本,Linux和mac用户可以根据requirements.txt配置环境后运行,建议是运行在venv环境中。 ## 开始使用它 - 1. 部署ictye live Danmku:你只需要简单的解压它就好,默认情况的启动脚本是为Windows用户提供的,不过在非Windows操作系统上,你仍旧可以使用`requirement.txt`来配置环境并且使用`python -m ictye-live-dm`来启动项目 2. 配置项目: 1. 这个软件是通过插件的形式来实现弹幕的获取,弹幕的分析和处理 @@ -24,7 +20,3 @@ 3. `/web/`里都是前端的资源,其中`/web/api`和`/web/cgi`是一个占位用的文件夹(方便开发。。。。。。。。。),`/web/js/`中是存放的前端的脚本,此外,你可以编辑style内的文件来定义你自己的样式 这个项目目前完全是我一个人开发(属实有点离谱),如果有想参加开发的可以联系我。。。。。。 - -剩余的工作: -- 找bug和打补丁。。。。。。。。。 -- 稳定性校验 \ No newline at end of file diff --git a/ictye-live-dm/src/ictye_live_dm/GUI/Ui_MainWindow.py b/ictye-live-dm/src/ictye_live_dm/GUI/Ui_MainWindow.py index 1e86467..6c6a1d6 100644 --- a/ictye-live-dm/src/ictye_live_dm/GUI/Ui_MainWindow.py +++ b/ictye-live-dm/src/ictye_live_dm/GUI/Ui_MainWindow.py @@ -1,9 +1,8 @@ # -*- coding: utf-8 -*- - -# Form implementation generated from reading ui file './main.ui' +# Form implementation generated from reading ui file '.\main.ui' # -# Created by: PyQt5 UI code generator 5.15.11 +# Created by: PyQt5 UI code generator 5.15.10 # # WARNING: Any manual changes made to this file will be lost when pyuic5 is # run again. Do not edit this file unless you know what you are doing. @@ -25,10 +24,10 @@ def setupUi(self, Form): self.verticalLayout.setObjectName("verticalLayout") self.horizontalLayout = QtWidgets.QHBoxLayout() self.horizontalLayout.setObjectName("horizontalLayout") - self.label = QtWidgets.QLabel(Form) - self.label.setMinimumSize(QtCore.QSize(223, 28)) - self.label.setObjectName("label") - self.horizontalLayout.addWidget(self.label) + self.shangdiyagou = QtWidgets.QLabel(Form) + self.shangdiyagou.setMinimumSize(QtCore.QSize(223, 28)) + self.shangdiyagou.setObjectName("shangdiyagou") + self.horizontalLayout.addWidget(self.shangdiyagou) self.startButtoen = QtWidgets.QPushButton(Form) self.startButtoen.setMaximumSize(QtCore.QSize(317, 28)) self.startButtoen.setObjectName("startButtoen") @@ -72,19 +71,19 @@ def setupUi(self, Form): spacerItem1 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum) self.horizontalLayout_7.addItem(spacerItem1) self.verticalLayout_6.addLayout(self.horizontalLayout_7) - self.adress_content_list = QtWidgets.QListWidget(self.tab_2) - self.adress_content_list.setObjectName("adress_content_list") - self.verticalLayout_6.addWidget(self.adress_content_list) + self.treeWidget = QtWidgets.QTreeWidget(self.tab_2) + self.treeWidget.setObjectName("treeWidget") + self.verticalLayout_6.addWidget(self.treeWidget) self.horizontalLayout_8 = QtWidgets.QHBoxLayout() self.horizontalLayout_8.setObjectName("horizontalLayout_8") - self.label_5 = QtWidgets.QLabel(self.tab_2) - self.label_5.setObjectName("label_5") - self.horizontalLayout_8.addWidget(self.label_5) + self.location = QtWidgets.QLabel(self.tab_2) + self.location.setObjectName("location") + self.horizontalLayout_8.addWidget(self.location) spacerItem2 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum) self.horizontalLayout_8.addItem(spacerItem2) - self.pushButton_4 = QtWidgets.QPushButton(self.tab_2) - self.pushButton_4.setObjectName("pushButton_4") - self.horizontalLayout_8.addWidget(self.pushButton_4) + self.openInBlsower = QtWidgets.QPushButton(self.tab_2) + self.openInBlsower.setObjectName("openInBlsower") + self.horizontalLayout_8.addWidget(self.openInBlsower) self.verticalLayout_6.addLayout(self.horizontalLayout_8) self.tabWidget.addTab(self.tab_2, "") self.log_Tab = QtWidgets.QWidget() @@ -144,7 +143,7 @@ def setupUi(self, Form): self.pluginListTable.setEditTriggers(QtWidgets.QAbstractItemView.NoEditTriggers) self.pluginListTable.setSelectionMode(QtWidgets.QAbstractItemView.NoSelection) self.pluginListTable.setObjectName("pluginListTable") - self.pluginListTable.setColumnCount(4) + self.pluginListTable.setColumnCount(5) self.pluginListTable.setRowCount(0) item = QtWidgets.QTableWidgetItem() self.pluginListTable.setHorizontalHeaderItem(0, item) @@ -154,6 +153,8 @@ def setupUi(self, Form): self.pluginListTable.setHorizontalHeaderItem(2, item) item = QtWidgets.QTableWidgetItem() self.pluginListTable.setHorizontalHeaderItem(3, item) + item = QtWidgets.QTableWidgetItem() + self.pluginListTable.setHorizontalHeaderItem(4, item) self.pluginListTable.horizontalHeader().setCascadingSectionResizes(False) self.pluginListTable.horizontalHeader().setSortIndicatorShown(False) self.pluginListTable.horizontalHeader().setStretchLastSection(True) @@ -290,22 +291,23 @@ def setupUi(self, Form): self.verticalLayout_3.addWidget(self.settingScrollArea) self.tabWidget.addTab(self.setting_Tab, "") self.verticalLayout.addWidget(self.tabWidget) + self.retranslateUi(Form) - self.tabWidget.setCurrentIndex(3) + self.tabWidget.setCurrentIndex(0) QtCore.QMetaObject.connectSlotsByName(Form) def retranslateUi(self, Form): _translate = QtCore.QCoreApplication.translate Form.setWindowTitle(_translate("Form", "Ictye Live Danmmku")) - self.label.setText(_translate("Form", "本項目由美國聖地亞哥(American Sangdiyagou)獨家贊助研發(x)")) + self.shangdiyagou.setText(_translate("Form", "本項目由美國聖地亞哥(American Sangdiyagou)獨家贊助研發(x)")) self.startButtoen.setText(_translate("Form", "Start")) self.stopButton.setText(_translate("Form", "Stop")) self.label_2.setText(_translate("Form", "

Home

")) self.StatusLable.setText(_translate("Form", "Status:")) self.status_display_lable.setText(_translate("Form", "%1")) self.label_3.setText(_translate("Form", "

Address Contents

")) - self.label_5.setText(_translate("Form", "

Location http://127.0.0.1:8082

")) - self.pushButton_4.setText(_translate("Form", "open in blsower")) + self.location.setText(_translate("Form", "

Location http://127.0.0.1:8082

")) + self.openInBlsower.setText(_translate("Form", "open in blsower")) self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab_2), _translate("Form", "Hone")) self.totalLogLable.setText(_translate("Form", "Total")) self.followCheckBox.setText(_translate("Form", "Follow newest log")) @@ -320,12 +322,14 @@ def retranslateUi(self, Form): self.pluginTotalLable.setText(_translate("Form", "Total:")) self.pushButton.setText(_translate("Form", "Submit")) item = self.pluginListTable.horizontalHeaderItem(0) - item.setText(_translate("Form", "Plugin name")) + item.setText(_translate("Form", "Plugin Name")) item = self.pluginListTable.horizontalHeaderItem(1) item.setText(_translate("Form", "Author")) item = self.pluginListTable.horizontalHeaderItem(2) item.setText(_translate("Form", "Version")) item = self.pluginListTable.horizontalHeaderItem(3) + item.setText(_translate("Form", "Plugin Type")) + item = self.pluginListTable.horizontalHeaderItem(4) item.setText(_translate("Form", "Description")) self.tabWidget.setTabText(self.tabWidget.indexOf(self.pluginListPage), _translate("Form", "Plugins")) self.label_4.setText(_translate("Form", "Port")) diff --git a/ictye-live-dm/src/ictye_live_dm/GUI_main.py b/ictye-live-dm/src/ictye_live_dm/GUI_main.py index 63044e1..31b77b2 100644 --- a/ictye-live-dm/src/ictye_live_dm/GUI_main.py +++ b/ictye-live-dm/src/ictye_live_dm/GUI_main.py @@ -82,11 +82,13 @@ def __init__(self, parent=None): self.init_setting_tab() self.retranslateUi(self) self._server = ServerClass() + self.startButtoen.clicked.connect(self.start_series) self.stopButton.clicked.connect(self.stop_series) + self.settingTreeWidget.expandAll() - self.status_display_lable.setText("Stopped") + self.status_display_lable.setText("Stopped") # set default status def init_setting_tab(self): config = configs.ConfigManager() @@ -129,12 +131,15 @@ def table_follow(self): self.logTable.scrollToBottom() def show_plugin_list(self): - plugins = pluginsystem.Plugin().list_plugin() + plugins = pluginsystem.Plugin().list_plugin_desc() for i in plugins: row = self.pluginListTable.rowCount() self.pluginListTable.insertRow(row) - self.pluginListTable.setItem(row, 0, QtWidgets.QTableWidgetItem(i[0])) - self.pluginListTable.setItem(row, 1, QtWidgets.QTableWidgetItem(i[1])) + self.pluginListTable.setItem(row, 0, QtWidgets.QTableWidgetItem(i["name"])) + self.pluginListTable.setItem(row, 1, QtWidgets.QTableWidgetItem(i["author"])) + self.pluginListTable.setItem(row, 2, QtWidgets.QTableWidgetItem(i["version"])) + self.pluginListTable.setItem(row, 3, QtWidgets.QTableWidgetItem(i["type"])) + self.pluginListTable.setItem(row, 4, QtWidgets.QTableWidgetItem(i["description"])) class ServerClass: diff --git a/ictye-live-dm/src/ictye_live_dm/QT-GUI/main.ui b/ictye-live-dm/src/ictye_live_dm/QT-GUI/main.ui index 6cbf0a3..50c9ffd 100644 --- a/ictye-live-dm/src/ictye_live_dm/QT-GUI/main.ui +++ b/ictye-live-dm/src/ictye_live_dm/QT-GUI/main.ui @@ -27,7 +27,7 @@ - + 223 @@ -79,7 +79,7 @@ QTabWidget::Rounded - 3 + 0 Qt::ElideNone @@ -158,12 +158,18 @@ - + + + + + + + - + <html><head/><body><p><span style=" font-size:x-large; font-weight:600;">Location </span><a href="http://127.0.0.1:8082"><span style=" text-decoration: underline; color:#0000ff;">http://127.0.0.1:8082</span></a></p></body></html> @@ -183,7 +189,7 @@ - + open in blsower @@ -313,7 +319,6 @@ QAbstractItemView::NoSelection - false @@ -325,7 +330,7 @@ - Plugin name + Plugin Name @@ -338,6 +343,11 @@ Version + + + Plugin Type + + Description diff --git a/ictye-live-dm/src/ictye_live_dm/depends/config_registrar.py b/ictye-live-dm/src/ictye_live_dm/depends/config_registrar.py index 59a94d6..34b0a06 100644 --- a/ictye-live-dm/src/ictye_live_dm/depends/config_registrar.py +++ b/ictye-live-dm/src/ictye_live_dm/depends/config_registrar.py @@ -619,6 +619,7 @@ def __len__(self): # config schemas ic_cfg_type = ConfigTree | ConfigKey +"""ictye 配置類型""" class ABConfigSchema(metaclass=ABCMeta): @@ -1025,12 +1026,12 @@ def __init__(self, self.type_ = s_dict self.properties = properties - def __find_additional_properties(self, other: ConfigTree) -> dict: + def __find_additional_properties(self, other: ConfigTree, additional: bool = True) -> dict: k_set: dict = {} for k, v in other.items(): - if k in self.properties.keys(): + if (k in self.properties.keys()) and additional: k_set[k] = v - if any([re.match(dk, k) for dk, dv in self.pattern_properties]): + if any([re.match(dk, k) for dk, dv in self.pattern_properties]) and additional: k_set[k] = v return k_set @@ -1101,7 +1102,7 @@ def __init__(self, title: str = "", description: str = "", _comment: str = "", - const: ConfigTree | ConfigKey = None, + const: ic_cfg_type = None, all_of: list["ABConfigSchema"] = None, any_of: list["ABConfigSchema"] = None, one_of: list["ABConfigSchema"] = None, diff --git a/ictye-live-dm/src/ictye_live_dm/depends/pluginmain.py b/ictye-live-dm/src/ictye_live_dm/depends/pluginmain.py index 503a870..853122b 100644 --- a/ictye-live-dm/src/ictye_live_dm/depends/pluginmain.py +++ b/ictye-live-dm/src/ictye_live_dm/depends/pluginmain.py @@ -12,11 +12,34 @@ class PluginConfig: def __init__(self, plugin_name: str): self.__config = config_registrar.ConfigTree() - def __get__(self, instance, owner: "PluginMain"): + def __get__(self, instance, owner: "PluginMain") -> config_registrar.ConfigTree: return self.__config - def register(self, value, name: str, default: typing.Any = None, schema: config_registrar.ConfigSchema = None): - ... + def register(self, value: config_registrar.ConfigKey | dict | config_registrar.ConfigTree, name: str, + default: typing.Any = None, schema: config_registrar.ConfigSchema = None): + if isinstance(value, dict): + self.__config.set(name, config_registrar.ConfigTree(build_dict=value, default=default, schema=schema)) + elif isinstance(value, list): + self.__config.set(name, config_registrar.ConfigTree(build_list=value, default=default, schema=schema)) + elif isinstance(value, config_registrar.ConfigKey): + self.__config.set(name, value) + elif isinstance(value, config_registrar.ConfigTree): + self.__config.set(name, value) + else: + self.__config.set(name, config_registrar.ConfigKey(value=value, default=default)) + + +class PluginDesc: + + def __get__(self, instance: "PluginMain", owner: "PluginMain") -> dict: + return { + "name" : instance.plugin_name, + "version" : instance.plugin_version, + "author" : instance.plugin_author, + "description": instance.plugin_desc, + "type" : instance.type, + "dev_branch" : instance.plugin_dev_beach, + } class PluginMain(metaclass=ABCMeta): @@ -57,6 +80,7 @@ class PluginMain(metaclass=ABCMeta): """cgi列表""" plugin_config = PluginConfig(plugin_name) + plugin_descriptor = PluginDesc() def __new__(cls, *args, **kwargs): if not cls._instance: @@ -142,6 +166,11 @@ def read_config(self): assert self.plugin_name != "" self.config = configs.read_config(self.plugin_name) + @typing.final + def get_description(self) -> str: + # TODO: 完善插件描述 + ... + def __aiter__(self): if self.plugin_type() == "message": return self diff --git a/ictye-live-dm/src/ictye_live_dm/http_server.py b/ictye-live-dm/src/ictye_live_dm/http_server.py index 0ab25cb..8ac9658 100644 --- a/ictye-live-dm/src/ictye_live_dm/http_server.py +++ b/ictye-live-dm/src/ictye_live_dm/http_server.py @@ -15,6 +15,7 @@ log = logging.getLogger(__name__) runner: Optional[web.AppRunner] = None + def return_file(file: str): async def header(request): nonlocal file @@ -91,7 +92,7 @@ async def http_cgi(request: web.Request): if request.match_info["name"] in plugin_system.plugin_cgi_support: if request.match_info["page"] in plugin_system.plugin_cgi_support[request.match_info["name"]]: req = await plugin_system.plugin_cgi_support[request.match_info["name"]][request.match_info["page"]]( - request) + request) else: req = web.Response(status=404, text="no such path") else: diff --git a/ictye-live-dm/src/ictye_live_dm/pluginsystem.py b/ictye-live-dm/src/ictye_live_dm/pluginsystem.py index 47bd711..3369cfa 100644 --- a/ictye-live-dm/src/ictye_live_dm/pluginsystem.py +++ b/ictye-live-dm/src/ictye_live_dm/pluginsystem.py @@ -6,7 +6,7 @@ import aiohttp.web as web -from .depends import pluginmain, plugin_errors, configs,config_registrar +from .depends import pluginmain, plugin_errors, configs, config_registrar config: configs.ConfigManager = configs.ConfigManager() # 配置 @@ -87,13 +87,21 @@ def __lod_init_plugin__(self): self.logger.error(f"failed to import plugin :\n{plugin_name} {str(e)}") def list_plugin(self) -> list: - plugins = [] + plugins: list = [] for plugin in self.message_plugin_list: plugins.append((plugin.plugin_name, plugin.plugin_desc)) for plugin in self.analyzer_plugin_list: plugins.append((plugin.plugin_name, plugin.plugin_desc)) return plugins + def list_plugin_desc(self) -> list: + plugins: list = [] + for plugin in self.message_plugin_list: + plugins.append(plugin.plugin_descriptor) + for plugin in self.analyzer_plugin_list: + plugins.append(plugin.plugin_descriptor) + return plugins + async def remove_connect_in_id_dict_aiohttp(self, id): """ 当连接关闭时,移除连接 diff --git a/ictye-live-dm/tests/Config_schema_test.py b/ictye-live-dm/tests/Config_schema_test.py index bc29b83..5a3ed0f 100644 --- a/ictye-live-dm/tests/Config_schema_test.py +++ b/ictye-live-dm/tests/Config_schema_test.py @@ -76,7 +76,7 @@ def test_bool_schema(config_key_bool): def test_dict_schema(config_tree_dict): properties = { 'name': StringSchema(), - 'age': IntSchema() + 'age' : IntSchema() } schema = DictSchema(properties) assert schema.verify(config_tree_dict) == True