From 49cb760d4df07ebb84eb2b6e6da75f5d49cee60d Mon Sep 17 00:00:00 2001 From: helloplhm-qwq Date: Sat, 11 Nov 2023 18:16:03 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E4=BE=BF=E6=90=BA=E7=89=88EXE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 5 ++++ apis/.github/workflows/build_binary.yml | 39 +++++++++++++++++++++++++ apis/__init__.py | 13 +++++++-- common/config.py | 24 +++++++++------ common/log.py | 18 ++++++++++-- common/lxsecurity.py | 4 --- common/sql/create_cache_db.sql | 5 ---- common/sql/create_data_db.sql | 3 -- common/utils.py | 5 ++++ main.py | 8 +++-- requirements.txt | 1 + 11 files changed, 96 insertions(+), 29 deletions(-) create mode 100644 apis/.github/workflows/build_binary.yml delete mode 100644 common/sql/create_cache_db.sql delete mode 100644 common/sql/create_data_db.sql diff --git a/.gitignore b/.gitignore index 8a51798..9126598 100644 --- a/.gitignore +++ b/.gitignore @@ -10,6 +10,11 @@ __pycache__/ *.egg-info *.egg +# pyinstaller +*.spec +dist +build + # project cache.db data.db diff --git a/apis/.github/workflows/build_binary.yml b/apis/.github/workflows/build_binary.yml new file mode 100644 index 0000000..5a202bb --- /dev/null +++ b/apis/.github/workflows/build_binary.yml @@ -0,0 +1,39 @@ +# this workflow using github actions to build a binary exe file for windows users + +name: build Windows exe + +on: + push: + branches: [main] + pull_request: + branches: [main] + +jobs: + build-exe: + runs-on: windows-latest + steps: + - name: checkout + uses: actions/checkout@v2 + + - name: setup python 3.11 + uses: actions/setup-python@v2 + with: + python-version: '3.11' + + - name: install pyinstaller + run: python -m pip install pyinstaller + + - name: install dependencies + run: python -m pip install -r ./requirements.txt + + - name: build exe + run: pyinstaller -F main.py + + - name: rename + run: Rename-Item ./dist/main.exe ./dist/lx-music-api-server_$(git rev-parse --short HEAD).exe + + - name: upload + uses: actions/upload-artifact@v2 + with: + name: lx-music-api-server + path: ./dist \ No newline at end of file diff --git a/apis/__init__.py b/apis/__init__.py index 9139140..789275e 100644 --- a/apis/__init__.py +++ b/apis/__init__.py @@ -8,8 +8,8 @@ # This file is part of the "lx-music-api-server" project. # Do not edit except you konw what you are doing. -from common.utils import require from common.exceptions import FailedException +from common.utils import require from common import log from common import config from . import kw @@ -59,8 +59,15 @@ async def SongURL(source, songId, quality): 'data': c['url'], } except: - traceback.print_exc() - func = require('apis.' + source).url + logger.error(traceback.format_exc()) + try: + func = require('apis.' + source).url + except: + return { + 'code': 1, + 'msg': '未知的源: ' + source, + 'data': None, + } try: url = await func(songId, quality) logger.debug(f'获取{source}_{songId}_{quality}成功,URL:{url}') diff --git a/common/config.py b/common/config.py index 47bc0b8..35895db 100644 --- a/common/config.py +++ b/common/config.py @@ -14,32 +14,34 @@ import os import traceback import sys import sqlite3 -from .utils import unique_list, readfile +from .utils import readfile from . import variable from .log import log -# from dbutils.pooled_db import PooledDB import threading +logger = log('config_manager') + # 创建线程本地存储对象 local_data = threading.local() + def get_data_connection(): # 检查线程本地存储对象是否存在连接对象,如果不存在则创建一个新的连接对象 if not hasattr(local_data, 'connection'): local_data.connection = sqlite3.connect('data.db') return local_data.connection + # 创建线程本地存储对象 local_cache = threading.local() + def get_cache_connection(): # 检查线程本地存储对象是否存在连接对象,如果不存在则创建一个新的连接对象 if not hasattr(local_cache, 'connection'): local_cache.connection = sqlite3.connect('cache.db') return local_cache.connection -logger = log('config_manager') - class ConfigReadException(Exception): pass @@ -395,8 +397,11 @@ def initConfig(): cursor = conn.cursor() # 创建一个表来存储缓存数据 - cursor.execute(readfile(variable.workdir + - '/common/sql/create_cache_db.sql')) + cursor.execute('''CREATE TABLE IF NOT EXISTS cache +(id INTEGER PRIMARY KEY AUTOINCREMENT, +module TEXT NOT NULL, +key TEXT NOT NULL, +data TEXT NOT NULL)''') conn.close() @@ -405,8 +410,9 @@ def initConfig(): # 创建一个游标对象 cursor2 = conn2.cursor() - cursor2.execute(readfile(variable.workdir + - '/common/sql/create_data_db.sql')) + cursor2.execute('''CREATE TABLE IF NOT EXISTS data +(key TEXT PRIMARY KEY, +value TEXT)''') conn2.close() @@ -416,7 +422,7 @@ def initConfig(): if (load_data() == {}): write_data('banList', []) write_data('requestTime', {}) - logger.debug('数据库内容为空,已写入默认值') + logger.info('数据库内容为空,已写入默认值') def ban_ip(ip_addr, ban_time=-1): diff --git a/common/log.py b/common/log.py index ecd9f9f..886829d 100644 --- a/common/log.py +++ b/common/log.py @@ -11,6 +11,10 @@ import logging import colorlog import os +import traceback +from pygments import highlight +from pygments.lexers import PythonLexer +from pygments.formatters import TerminalFormatter from .utils import sanitize_filename from .variable import debug_mode, log_length_limit @@ -19,6 +23,13 @@ try: except: pass +def highlight_error(error): + # 对堆栈跟踪进行语法高亮 + highlighted_traceback = highlight(error, PythonLexer(), TerminalFormatter()) + + # 返回语法高亮后的堆栈跟踪字符串 + return str(highlighted_traceback) + class flaskLogHelper(logging.Handler): # werkzeug日志转接器 def __init__(self, custom_logger): @@ -45,7 +56,7 @@ class log: datefmt='%Y-%m-%d %H:%M:%S', log_colors={ 'DEBUG': 'cyan', - 'INFO': 'green', + 'INFO': 'white', 'WARNING': 'yellow', 'ERROR': 'red', 'CRITICAL': 'red,bg_white', @@ -120,7 +131,10 @@ class log: self._logger.warning(message) def error(self, message): - self._logger.error(message) + if (message.startswith('Traceback')): + self._logger.error('\n' + highlight_error(message)) + else: + self._logger.error(message) def critical(self, message): self._logger.critical(message) diff --git a/common/lxsecurity.py b/common/lxsecurity.py index d252787..7da9cbe 100644 --- a/common/lxsecurity.py +++ b/common/lxsecurity.py @@ -37,7 +37,3 @@ def checklxmheader(lxm, url): return True except: return False - -exports = { - -} \ No newline at end of file diff --git a/common/sql/create_cache_db.sql b/common/sql/create_cache_db.sql deleted file mode 100644 index afaa00c..0000000 --- a/common/sql/create_cache_db.sql +++ /dev/null @@ -1,5 +0,0 @@ -CREATE TABLE IF NOT EXISTS cache -(id INTEGER PRIMARY KEY AUTOINCREMENT, -module TEXT NOT NULL, -key TEXT NOT NULL, -data TEXT NOT NULL) \ No newline at end of file diff --git a/common/sql/create_data_db.sql b/common/sql/create_data_db.sql deleted file mode 100644 index ba8b7fa..0000000 --- a/common/sql/create_data_db.sql +++ /dev/null @@ -1,3 +0,0 @@ -CREATE TABLE IF NOT EXISTS data -(key TEXT PRIMARY KEY, -value TEXT) \ No newline at end of file diff --git a/common/utils.py b/common/utils.py index c333ef4..e803ef9 100644 --- a/common/utils.py +++ b/common/utils.py @@ -10,6 +10,7 @@ import platform import binascii +import builtins import base64 import zlib import re @@ -51,6 +52,9 @@ def require(module): index += 1 return _module +def add_to_global_namespace(key, data): + setattr(builtins, key, data) + def sanitize_filename(filename): if platform.system() == 'Windows' or platform.system() == 'Cygwin': # Windows不合法文件名字符 @@ -129,3 +133,4 @@ class jsobject(dict): def __getattr__(self, UNUSED): return None +add_to_global_namespace('require', require) \ No newline at end of file diff --git a/main.py b/main.py index a1fff45..ea3321e 100644 --- a/main.py +++ b/main.py @@ -29,8 +29,6 @@ from common import utils from common import lxsecurity from apis import SongURL -require = utils.require - @app.route('/') def index(): return utils.format_dict_json({"code": 0, "msg": "success", "data": None}), 200 @@ -64,16 +62,20 @@ def _404(_): @app.before_request def check(): + # nginx proxy header if (request.headers.get("X-Real-IP")): request.remote_addr = request.headers.get("X-Real-IP") + # check ip if (config.check_ip_banned(request.remote_addr)): return utils.format_dict_json({"code": 1, "msg": "您的IP已被封禁", "data": None}), 403 + # update request time config.updateRequestTime(request.remote_addr) + # check host if (config.read_config("security.allowed_host.enable")): if request.remote_host.split(":")[0] not in config.read_config("security.allowed_host.list"): if config.read_config("security.allowed_host.blacklist.enable"): config.ban_ip(request.remote_addr, int(config.read_config("security.allowed_host.blacklist.length"))) return utils.format_dict_json({'code': 6, 'msg': '未找到您所请求的资源', 'data': None}), 404 - +# run app.run(host=config.read_config('common.host'), port=config.read_config('common.port')) diff --git a/requirements.txt b/requirements.txt index fff6db3..fb6ced0 100644 --- a/requirements.txt +++ b/requirements.txt @@ -3,3 +3,4 @@ pycryptodome ujson requests colorlog +pygments