From eea316865f156e69229da92d078c8ea320e53619 Mon Sep 17 00:00:00 2001 From: jxxghp Date: Mon, 9 Oct 2023 11:05:53 +0800 Subject: [PATCH 01/18] fix #753 --- app/plugins/iyuuautoseed/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/plugins/iyuuautoseed/__init__.py b/app/plugins/iyuuautoseed/__init__.py index bcfe01c2..9e5ff84f 100644 --- a/app/plugins/iyuuautoseed/__init__.py +++ b/app/plugins/iyuuautoseed/__init__.py @@ -109,7 +109,7 @@ class IYUUAutoSeed(_PluginBase): self._nolabels = config.get("nolabels") self._nopaths = config.get("nopaths") self._clearcache = config.get("clearcache") - self._permanent_error_caches = config.get("permanent_error_caches") or [] + self._permanent_error_caches = [] if self._clearcache else config.get("permanent_error_caches") or [] self._error_caches = [] if self._clearcache else config.get("error_caches") or [] self._success_caches = [] if self._clearcache else config.get("success_caches") or [] From 97f16289c978da9ce622603d9adfa91044aad491 Mon Sep 17 00:00:00 2001 From: jxxghp Date: Mon, 9 Oct 2023 12:57:52 +0800 Subject: [PATCH 02/18] windows package --- .github/workflows/build-windows.yml | 36 +++++++ .github/workflows/build.yml | 2 +- app.ico | Bin 0 -> 178217 bytes app/core/config.py | 14 ++- app/db/init.py | 2 +- app/helper/display.py | 3 + app/utils/system.py | 20 ++++ config/app.env | 84 +++++++-------- {alembic => database}/env.py | 0 {alembic => database}/gen.py | 2 +- {alembic => database}/script.py.mako | 0 .../versions/14f1813ae8e3_1_0_1.py | 0 .../versions/1e169250e949_1_0_4.py | 0 .../versions/232dfa044617_1_0_6.py | 0 .../versions/30329639c12b_1_0_7.py | 0 .../versions/52ab4930be04_1_0_3.py | 0 .../versions/9f4edd55c2d4_1_0_0.py | 0 .../versions/a521fbc28b18_1_0_9.py | 0 .../versions/b2f011d3a8b7_1_0_8.py | 0 .../versions/e734c7fe6056_1_0_5.py | 0 .../versions/ec5fb51fc300_1_0_2.py | 0 windows.spec | 101 ++++++++++++++++++ 22 files changed, 217 insertions(+), 47 deletions(-) create mode 100644 .github/workflows/build-windows.yml create mode 100644 app.ico rename {alembic => database}/env.py (100%) rename {alembic => database}/gen.py (92%) rename {alembic => database}/script.py.mako (100%) rename {alembic => database}/versions/14f1813ae8e3_1_0_1.py (100%) rename {alembic => database}/versions/1e169250e949_1_0_4.py (100%) rename {alembic => database}/versions/232dfa044617_1_0_6.py (100%) rename {alembic => database}/versions/30329639c12b_1_0_7.py (100%) rename {alembic => database}/versions/52ab4930be04_1_0_3.py (100%) rename {alembic => database}/versions/9f4edd55c2d4_1_0_0.py (100%) rename {alembic => database}/versions/a521fbc28b18_1_0_9.py (100%) rename {alembic => database}/versions/b2f011d3a8b7_1_0_8.py (100%) rename {alembic => database}/versions/e734c7fe6056_1_0_5.py (100%) rename {alembic => database}/versions/ec5fb51fc300_1_0_2.py (100%) create mode 100644 windows.spec diff --git a/.github/workflows/build-windows.yml b/.github/workflows/build-windows.yml new file mode 100644 index 00000000..129e10af --- /dev/null +++ b/.github/workflows/build-windows.yml @@ -0,0 +1,36 @@ +name: MoviePilot Windows Builder +on: + workflow_dispatch: + push: + branches: + - master + paths: + - version.py + - .github/workflows/build-windows.yml + +jobs: + Windows-build: + runs-on: windows-latest + steps: + - name: Init Python 3.11.4 + uses: actions/setup-python@v4 + with: + python-version: '3.11.4' + - name: Install Dependent Packages + run: | + python -m pip install --upgrade pip + pip install wheel numpy==1.23.5 pyparsing==3.0.9 wxpython==4.2.0 pyinstaller==5.7.0 + git clone --depth=1 -b main https://github.com/jxxghp/MoviePilot + cd MoviePilot + pip install -r requirements.txt + shell: pwsh + - name: Pyinstaller + run: | + cd MoviePilot + pyinstaller windows.spec + shell: pwsh + - name: Upload Windows File + uses: actions/upload-artifact@v3 + with: + name: windows + path: MoviePilot/dist/MoviePilot.exe diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 81a2fe45..affd37c5 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -1,4 +1,4 @@ -name: MoviePilot Builder +name: MoviePilot Docker Builder on: workflow_dispatch: push: diff --git a/app.ico b/app.ico new file mode 100644 index 0000000000000000000000000000000000000000..18d99480283cda041765d07b3b54f0713497ec28 GIT binary patch literal 178217 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 bpV7veziz?r6`O#Y^%*=}{an^LB{Ts5?;k%r literal 0 HcmV?d00001 diff --git a/app/core/config.py b/app/core/config.py index 2d720370..8bf7dd84 100644 --- a/app/core/config.py +++ b/app/core/config.py @@ -1,10 +1,13 @@ import os import secrets +import sys from pathlib import Path from typing import List from pydantic import BaseSettings +from app.utils.system import SystemUtils + class Settings(BaseSettings): # 项目名称 @@ -28,7 +31,7 @@ class Settings(BaseSettings): # 是否开发模式 DEV: bool = False # 配置文件目录 - CONFIG_DIR: str = "/config" + CONFIG_DIR: str = None # 超级管理员 SUPERUSER: str = "admin" # 超级管理员初始密码 @@ -209,7 +212,11 @@ class Settings(BaseSettings): def CONFIG_PATH(self): if self.CONFIG_DIR: return Path(self.CONFIG_DIR) - return self.INNER_CONFIG_PATH + elif SystemUtils.is_docker(): + return Path("/config") + elif SystemUtils.is_frozen(): + return Path(sys.executable).parent / "config" + return self.ROOT_PATH / "config" @property def TEMP_PATH(self): @@ -274,6 +281,9 @@ class Settings(BaseSettings): with self.CONFIG_PATH as p: if not p.exists(): p.mkdir(parents=True, exist_ok=True) + if SystemUtils.is_frozen(): + if not (p / "app.env").exists(): + SystemUtils.copy(self.INNER_CONFIG_PATH / "app.env", p / "app.env") with self.TEMP_PATH as p: if not p.exists(): p.mkdir(parents=True, exist_ok=True) diff --git a/app/db/init.py b/app/db/init.py index c902c1fb..d5ee24b5 100644 --- a/app/db/init.py +++ b/app/db/init.py @@ -39,7 +39,7 @@ def update_db(): 更新数据库 """ db_location = settings.CONFIG_PATH / 'user.db' - script_location = settings.ROOT_PATH / 'alembic' + script_location = settings.ROOT_PATH / 'database' try: alembic_cfg = Config() alembic_cfg.set_main_option('script_location', str(script_location)) diff --git a/app/helper/display.py b/app/helper/display.py index 1ae6504a..06fb412b 100644 --- a/app/helper/display.py +++ b/app/helper/display.py @@ -2,12 +2,15 @@ from pyvirtualdisplay import Display from app.log import logger from app.utils.singleton import Singleton +from app.utils.system import SystemUtils class DisplayHelper(metaclass=Singleton): _display: Display = None def __init__(self): + if not SystemUtils.is_docker(): + return try: self._display = Display(visible=False, size=(1024, 768)) self._display.start() diff --git a/app/utils/system.py b/app/utils/system.py index e5a273aa..10243801 100644 --- a/app/utils/system.py +++ b/app/utils/system.py @@ -3,6 +3,7 @@ import os import platform import re import shutil +import sys from pathlib import Path from typing import List, Union, Tuple @@ -27,20 +28,39 @@ class SystemUtils: @staticmethod def is_docker() -> bool: + """ + 判断是否为Docker环境 + """ return Path("/.dockerenv").exists() @staticmethod def is_synology() -> bool: + """ + 判断是否为群晖系统 + """ if SystemUtils.is_windows(): return False return True if "synology" in SystemUtils.execute('uname -a') else False @staticmethod def is_windows() -> bool: + """ + 判断是否为Windows系统 + """ return True if os.name == "nt" else False + @staticmethod + def is_frozen() -> bool: + """ + 判断是否为冻结的二进制文件 + """ + return True if getattr(sys, 'frozen', False) else False + @staticmethod def is_macos() -> bool: + """ + 判断是否为MacOS系统 + """ return True if platform.system() == 'Darwin' else False @staticmethod diff --git a/config/app.env b/config/app.env index d0e25c90..4363817e 100644 --- a/config/app.env +++ b/config/app.env @@ -3,7 +3,7 @@ ####################################################################### #################################### -# 系统设置 # +# 基础设置 # #################################### # 时区 TZ=Asia/Shanghai @@ -21,6 +21,10 @@ SUPERUSER_PASSWORD=password API_TOKEN=moviepilot # 网络代理 IP:PORT PROXY_HOST= +# TMDB图片地址,无需修改需保留默认值 +TMDB_IMAGE_DOMAIN=image.tmdb.org +# TMDB API地址,无需修改需保留默认值 +TMDB_API_DOMAIN=api.themoviedb.org # 大内存模式 BIG_MEMORY_MODE=false @@ -35,13 +39,45 @@ SCRAP_METADATA=true SCRAP_FOLLOW_TMDB=true # 刮削来源 themoviedb/douban SCRAP_SOURCE=themoviedb -# TMDB图片地址,无需修改需保留默认值 -TMDB_IMAGE_DOMAIN=image.tmdb.org -# TMDB API地址,无需修改需保留默认值 -TMDB_API_DOMAIN=api.themoviedb.org #################################### -# 订阅&搜索 # +# 媒体库 # +#################################### +# 【*】转移方式 link/copy/move/softlink +TRANSFER_TYPE=copy +# 【*】媒体库目录,多个目录使用,分隔 +LIBRARY_PATH= +# 电影媒体库目录名,默认电影 +LIBRARY_MOVIE_NAME= +# 电视剧媒体库目录名,默认电视剧 +LIBRARY_TV_NAME= +# 动漫媒体库目录名,默认电视剧/动漫 +LIBRARY_ANIME_NAME= +# 二级分类 +LIBRARY_CATEGORY=true +# 电影重命名格式 +MOVIE_RENAME_FORMAT={{title}}{% if year %} ({{year}}){% endif %}/{{title}}{% if year %} ({{year}}){% endif %}{% if part %}-{{part}}{% endif %}{% if videoFormat %} - {{videoFormat}}{% endif %}{{fileExt}} +# 电视剧重命名格式 +TV_RENAME_FORMAT={{title}}{% if year %} ({{year}}){% endif %}/Season {{season}}/{{title}} - {{season_episode}}{% if part %}-{{part}}{% endif %}{% if episode %} - 第 {{episode}} 集{% endif %}{{fileExt}} + +#################################### +# 站点 # +#################################### +# 【*】CookieCloud服务器地址,默认为公共服务器 +COOKIECLOUD_HOST=https://movie-pilot.org/cookiecloud +# 【*】CookieCloud用户KEY +COOKIECLOUD_KEY= +# 【*】CookieCloud端对端加密密码 +COOKIECLOUD_PASSWORD= +# 【*】CookieCloud同步间隔(分钟) +COOKIECLOUD_INTERVAL=1440 +# OCR服务器地址 +OCR_HOST=https://movie-pilot.org +# 【*】CookieCloud对应的浏览器UA +USER_AGENT=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/113.0.0.0 Safari/537.36 Edg/113.0.1774.57 + +#################################### +# 订阅 & 搜索 # #################################### # 订阅模式 spider/rss SUBSCRIBE_MODE=spider @@ -149,39 +185,3 @@ JELLYFIN_API_KEY= PLEX_HOST= # Plex Token PLEX_TOKEN= - -#################################### -# 站点 # -#################################### -# 【*】CookieCloud服务器地址,默认为公共服务器 -COOKIECLOUD_HOST=https://movie-pilot.org/cookiecloud -# 【*】CookieCloud用户KEY -COOKIECLOUD_KEY= -# 【*】CookieCloud端对端加密密码 -COOKIECLOUD_PASSWORD= -# 【*】CookieCloud同步间隔(分钟) -COOKIECLOUD_INTERVAL=1440 -# OCR服务器地址 -OCR_HOST=https://movie-pilot.org -# 【*】CookieCloud对应的浏览器UA -USER_AGENT=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/113.0.0.0 Safari/537.36 Edg/113.0.1774.57 - -#################################### -# 媒体库 # -#################################### -# 【*】转移方式 link/copy/move/softlink -TRANSFER_TYPE=copy -# 【*】媒体库目录,多个目录使用,分隔 -LIBRARY_PATH= -# 电影媒体库目录名,默认电影 -LIBRARY_MOVIE_NAME= -# 电视剧媒体库目录名,默认电视剧 -LIBRARY_TV_NAME= -# 动漫媒体库目录名,默认电视剧/动漫 -LIBRARY_ANIME_NAME= -# 二级分类 -LIBRARY_CATEGORY=true -# 电影重命名格式 -MOVIE_RENAME_FORMAT={{title}}{% if year %} ({{year}}){% endif %}/{{title}}{% if year %} ({{year}}){% endif %}{% if part %}-{{part}}{% endif %}{% if videoFormat %} - {{videoFormat}}{% endif %}{{fileExt}} -# 电视剧重命名格式 -TV_RENAME_FORMAT={{title}}{% if year %} ({{year}}){% endif %}/Season {{season}}/{{title}} - {{season_episode}}{% if part %}-{{part}}{% endif %}{% if episode %} - 第 {{episode}} 集{% endif %}{{fileExt}} diff --git a/alembic/env.py b/database/env.py similarity index 100% rename from alembic/env.py rename to database/env.py diff --git a/alembic/gen.py b/database/gen.py similarity index 92% rename from alembic/gen.py rename to database/gen.py index 876b8525..9bf4edca 100644 --- a/alembic/gen.py +++ b/database/gen.py @@ -12,7 +12,7 @@ for module in Path(__file__).with_name("models").glob("*.py"): db_version = input("请输入版本号:") db_location = settings.CONFIG_PATH / 'user.db' -script_location = settings.ROOT_PATH / 'alembic' +script_location = settings.ROOT_PATH / 'database' alembic_cfg = AlembicConfig() alembic_cfg.set_main_option('script_location', str(script_location)) alembic_cfg.set_main_option('sqlalchemy.url', f"sqlite:///{db_location}") diff --git a/alembic/script.py.mako b/database/script.py.mako similarity index 100% rename from alembic/script.py.mako rename to database/script.py.mako diff --git a/alembic/versions/14f1813ae8e3_1_0_1.py b/database/versions/14f1813ae8e3_1_0_1.py similarity index 100% rename from alembic/versions/14f1813ae8e3_1_0_1.py rename to database/versions/14f1813ae8e3_1_0_1.py diff --git a/alembic/versions/1e169250e949_1_0_4.py b/database/versions/1e169250e949_1_0_4.py similarity index 100% rename from alembic/versions/1e169250e949_1_0_4.py rename to database/versions/1e169250e949_1_0_4.py diff --git a/alembic/versions/232dfa044617_1_0_6.py b/database/versions/232dfa044617_1_0_6.py similarity index 100% rename from alembic/versions/232dfa044617_1_0_6.py rename to database/versions/232dfa044617_1_0_6.py diff --git a/alembic/versions/30329639c12b_1_0_7.py b/database/versions/30329639c12b_1_0_7.py similarity index 100% rename from alembic/versions/30329639c12b_1_0_7.py rename to database/versions/30329639c12b_1_0_7.py diff --git a/alembic/versions/52ab4930be04_1_0_3.py b/database/versions/52ab4930be04_1_0_3.py similarity index 100% rename from alembic/versions/52ab4930be04_1_0_3.py rename to database/versions/52ab4930be04_1_0_3.py diff --git a/alembic/versions/9f4edd55c2d4_1_0_0.py b/database/versions/9f4edd55c2d4_1_0_0.py similarity index 100% rename from alembic/versions/9f4edd55c2d4_1_0_0.py rename to database/versions/9f4edd55c2d4_1_0_0.py diff --git a/alembic/versions/a521fbc28b18_1_0_9.py b/database/versions/a521fbc28b18_1_0_9.py similarity index 100% rename from alembic/versions/a521fbc28b18_1_0_9.py rename to database/versions/a521fbc28b18_1_0_9.py diff --git a/alembic/versions/b2f011d3a8b7_1_0_8.py b/database/versions/b2f011d3a8b7_1_0_8.py similarity index 100% rename from alembic/versions/b2f011d3a8b7_1_0_8.py rename to database/versions/b2f011d3a8b7_1_0_8.py diff --git a/alembic/versions/e734c7fe6056_1_0_5.py b/database/versions/e734c7fe6056_1_0_5.py similarity index 100% rename from alembic/versions/e734c7fe6056_1_0_5.py rename to database/versions/e734c7fe6056_1_0_5.py diff --git a/alembic/versions/ec5fb51fc300_1_0_2.py b/database/versions/ec5fb51fc300_1_0_2.py similarity index 100% rename from alembic/versions/ec5fb51fc300_1_0_2.py rename to database/versions/ec5fb51fc300_1_0_2.py diff --git a/windows.spec b/windows.spec new file mode 100644 index 00000000..ed451618 --- /dev/null +++ b/windows.spec @@ -0,0 +1,101 @@ +# -*- mode: python ; coding: utf-8 -*- + +def collect_pkg_data(package, include_py_files=False, subdir=None): + """ + Collect all data files from the given package. + """ + import os + from PyInstaller.utils.hooks import get_package_paths, remove_prefix, PY_IGNORE_EXTENSIONS + + # Accept only strings as packages. + if type(package) is not str: + raise ValueError + + pkg_base, pkg_dir = get_package_paths(package) + if subdir: + pkg_dir = os.path.join(pkg_dir, subdir) + # Walk through all file in the given package, looking for data files. + data_toc = TOC() + for dir_path, dir_names, files in os.walk(pkg_dir): + for f in files: + extension = os.path.splitext(f)[1] + if include_py_files or (extension not in PY_IGNORE_EXTENSIONS): + source_file = os.path.join(dir_path, f) + dest_folder = remove_prefix(dir_path, os.path.dirname(pkg_base) + os.sep) + dest_file = os.path.join(dest_folder, f) + data_toc.append((dest_file, source_file, 'DATA')) + return data_toc + + +def collect_local_submodules(package): + """ + Collect all local submodules from the given package. + """ + import os + base_dir = '..' + package_dir = os.path.join(base_dir, package.replace('.', os.sep)) + submodules = [] + for dir_path, dir_names, files in os.walk(package_dir): + for f in files: + if f == '__init__.py': + submodules.append(f"{package}.{os.path.basename(dir_path)}") + elif f.endswith('.py'): + submodules.append(f"{package}.{os.path.basename(dir_path)}.{os.path.splitext(f)[0]}") + for d in dir_names: + submodules.append(f"{package}.{os.path.basename(dir_path)}.{d}") + return submodules + + +hiddenimports = [ + 'passlib.handlers.bcrypt', + 'app.modules', + 'app.plugins', +] + collect_local_submodules('app.modules') \ + + collect_local_submodules('app.plugins') + +a = Analysis( + ['app/main.py'], + pathex=[], + binaries=[], + datas=[], + hiddenimports=hiddenimports, + hookspath=[], + hooksconfig={}, + runtime_hooks=[], + excludes=[], + noarchive=False, +) + +pyz = PYZ(a.pure) + +exe = EXE( + pyz, + a.scripts, + [], + exclude_binaries=True, + name='MoviePilot', + debug=False, + bootloader_ignore_signals=False, + strip=False, + upx=True, + console=True, + disable_windowed_traceback=False, + argv_emulation=False, + target_arch=None, + codesign_identity=None, + entitlements_file=None, + icon="app.ico" +) + +coll = COLLECT( + exe, + a.binaries, + a.datas, + collect_pkg_data('config'), + collect_pkg_data('cf_clearance'), + collect_pkg_data('database', include_py_files=True), + strip=False, + upx=True, + upx_exclude=[], + name='MoviePilot', +) From 38f7a31200910928b398a57286044718e5f26738 Mon Sep 17 00:00:00 2001 From: jxxghp Date: Mon, 9 Oct 2023 13:40:09 +0800 Subject: [PATCH 03/18] windows package --- .github/workflows/build-windows.yml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build-windows.yml b/.github/workflows/build-windows.yml index 129e10af..d932393f 100644 --- a/.github/workflows/build-windows.yml +++ b/.github/workflows/build-windows.yml @@ -19,18 +19,20 @@ jobs: - name: Install Dependent Packages run: | python -m pip install --upgrade pip - pip install wheel numpy==1.23.5 pyparsing==3.0.9 wxpython==4.2.0 pyinstaller==5.7.0 + pip install wheel pyinstaller git clone --depth=1 -b main https://github.com/jxxghp/MoviePilot cd MoviePilot pip install -r requirements.txt shell: pwsh + - name: Pyinstaller run: | cd MoviePilot pyinstaller windows.spec shell: pwsh + - name: Upload Windows File uses: actions/upload-artifact@v3 with: name: windows - path: MoviePilot/dist/MoviePilot.exe + path: MoviePilot/dist/MoviePilot/MoviePilot.exe From eaff557d706355afad0929b26137e407e8e7bb81 Mon Sep 17 00:00:00 2001 From: jxxghp Date: Mon, 9 Oct 2023 14:11:03 +0800 Subject: [PATCH 04/18] windows package --- .github/workflows/build-windows.yml | 3 +-- windows.spec | 22 ++++++++-------------- 2 files changed, 9 insertions(+), 16 deletions(-) diff --git a/.github/workflows/build-windows.yml b/.github/workflows/build-windows.yml index d932393f..22872d51 100644 --- a/.github/workflows/build-windows.yml +++ b/.github/workflows/build-windows.yml @@ -3,10 +3,9 @@ on: workflow_dispatch: push: branches: - - master + - main paths: - version.py - - .github/workflows/build-windows.yml jobs: Windows-build: diff --git a/windows.spec b/windows.spec index ed451618..60cdee9a 100644 --- a/windows.spec +++ b/windows.spec @@ -71,13 +71,20 @@ pyz = PYZ(a.pure) exe = EXE( pyz, a.scripts, + a.binaries, + a.zipfiles, + a.datas, + collect_pkg_data('config'), + collect_pkg_data('cf_clearance'), + collect_pkg_data('database', include_py_files=True), [], - exclude_binaries=True, name='MoviePilot', debug=False, bootloader_ignore_signals=False, strip=False, upx=True, + upx_exclude=[], + runtime_tmpdir=None, console=True, disable_windowed_traceback=False, argv_emulation=False, @@ -86,16 +93,3 @@ exe = EXE( entitlements_file=None, icon="app.ico" ) - -coll = COLLECT( - exe, - a.binaries, - a.datas, - collect_pkg_data('config'), - collect_pkg_data('cf_clearance'), - collect_pkg_data('database', include_py_files=True), - strip=False, - upx=True, - upx_exclude=[], - name='MoviePilot', -) From ef8ddcde078e5de7a85c78f0cc5ce71a5772800f Mon Sep 17 00:00:00 2001 From: jxxghp Date: Mon, 9 Oct 2023 14:46:23 +0800 Subject: [PATCH 05/18] fix --- .github/workflows/build-windows.yml | 2 +- windows.spec | 12 +++++++----- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/.github/workflows/build-windows.yml b/.github/workflows/build-windows.yml index 22872d51..ecbbbb82 100644 --- a/.github/workflows/build-windows.yml +++ b/.github/workflows/build-windows.yml @@ -34,4 +34,4 @@ jobs: uses: actions/upload-artifact@v3 with: name: windows - path: MoviePilot/dist/MoviePilot/MoviePilot.exe + path: MoviePilot/dist/MoviePilot.exe diff --git a/windows.spec b/windows.spec index 60cdee9a..62f1101b 100644 --- a/windows.spec +++ b/windows.spec @@ -47,12 +47,14 @@ def collect_local_submodules(package): hiddenimports = [ - 'passlib.handlers.bcrypt', - 'app.modules', - 'app.plugins', -] + collect_local_submodules('app.modules') \ + 'passlib.handlers.bcrypt', + 'app.modules', + 'app.plugins', + ] + collect_local_submodules('app.modules') \ + collect_local_submodules('app.plugins') +block_cipher = None + a = Analysis( ['app/main.py'], pathex=[], @@ -66,7 +68,7 @@ a = Analysis( noarchive=False, ) -pyz = PYZ(a.pure) +pyz = PYZ(a.pure, a.zipped_data, cipher=block_cipher) exe = EXE( pyz, From de128f5e6a9db8685450ab6f204a344e674aa5cc Mon Sep 17 00:00:00 2001 From: jxxghp Date: Mon, 9 Oct 2023 15:04:54 +0800 Subject: [PATCH 06/18] fix --- app/core/config.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/core/config.py b/app/core/config.py index 8bf7dd84..e0c7de10 100644 --- a/app/core/config.py +++ b/app/core/config.py @@ -296,6 +296,6 @@ class Settings(BaseSettings): settings = Settings( - _env_file=Path(os.environ.get("CONFIG_DIR", "/config")) / "app.env", + _env_file=Settings().CONFIG_PATH / "app.env", _env_file_encoding="utf-8" ) From 79b4d5fb8e6f38e2de0ef699d0d6c3e1eb2e0c5d Mon Sep 17 00:00:00 2001 From: jxxghp Date: Mon, 9 Oct 2023 19:33:05 +0800 Subject: [PATCH 07/18] fix build --- .github/workflows/build-windows.yml | 72 ++++++++++++++++++++--------- .github/workflows/build.yml | 23 ++++----- .github/workflows/release.yml | 36 --------------- 3 files changed, 58 insertions(+), 73 deletions(-) delete mode 100644 .github/workflows/release.yml diff --git a/.github/workflows/build-windows.yml b/.github/workflows/build-windows.yml index ecbbbb82..8aac3e3f 100644 --- a/.github/workflows/build-windows.yml +++ b/.github/workflows/build-windows.yml @@ -11,27 +11,55 @@ jobs: Windows-build: runs-on: windows-latest steps: - - name: Init Python 3.11.4 - uses: actions/setup-python@v4 - with: - python-version: '3.11.4' - - name: Install Dependent Packages - run: | - python -m pip install --upgrade pip - pip install wheel pyinstaller - git clone --depth=1 -b main https://github.com/jxxghp/MoviePilot - cd MoviePilot - pip install -r requirements.txt - shell: pwsh + - name: Checkout + uses: actions/checkout@v4 - - name: Pyinstaller - run: | - cd MoviePilot - pyinstaller windows.spec - shell: pwsh + - name: Release Version + id: release_version + run: | + app_version=$(cat version.py |sed -ne "s/APP_VERSION\s=\s'v\(.*\)'/\1/gp") + echo "app_version=$app_version" >> $GITHUB_ENV - - name: Upload Windows File - uses: actions/upload-artifact@v3 - with: - name: windows - path: MoviePilot/dist/MoviePilot.exe + - name: Generate Release + id: generate_release + uses: actions/create-release@latest + with: + tag_name: v${{ env.app_version }} + release_name: v${{ env.app_version }} + body: ${{ github.event.commits[0].message }} + draft: false + prerelease: false + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: Init Python 3.11.4 + uses: actions/setup-python@v4 + with: + python-version: '3.11.4' + + - name: Install Dependent Packages + run: | + python -m pip install --upgrade pip + pip install wheel pyinstaller + pip install -r requirements.txt + shell: pwsh + + - name: Pyinstaller + run: | + pyinstaller windows.spec + shell: pwsh + + - name: Upload Windows File + uses: actions/upload-artifact@v3 + with: + name: windows + path: dist/MoviePilot.exe + + - name: Upload Release Asset + uses: dwenegar/upload-release-assets@v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + release_id: ${{ steps.generate_release.outputs.id }} + assets_path: | + dist/MoviePilot.exe diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index affd37c5..0b32b29d 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -8,23 +8,20 @@ on: - version.py jobs: - build: + Docker-build: runs-on: ubuntu-latest name: Build Docker Image steps: - - - name: Checkout + - name: Checkout uses: actions/checkout@v4 - - - name: Release version + - name: Release version id: release_version run: | app_version=$(cat version.py |sed -ne "s/APP_VERSION\s=\s'v\(.*\)'/\1/gp") echo "app_version=$app_version" >> $GITHUB_ENV - - - name: Docker meta + - name: Docker meta id: meta uses: docker/metadata-action@v5 with: @@ -33,23 +30,19 @@ jobs: type=raw,value=${{ env.app_version }} type=raw,value=latest - - - name: Set Up QEMU + - name: Set Up QEMU uses: docker/setup-qemu-action@v3 - - - name: Set Up Buildx + - name: Set Up Buildx uses: docker/setup-buildx-action@v3 - - - name: Login DockerHub + - name: Login DockerHub uses: docker/login-action@v3 with: username: ${{ secrets.DOCKER_USERNAME }} password: ${{ secrets.DOCKER_PASSWORD }} - - - name: Build Image + - name: Build Image uses: docker/build-push-action@v5 with: context: . diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml deleted file mode 100644 index 43c11bb5..00000000 --- a/.github/workflows/release.yml +++ /dev/null @@ -1,36 +0,0 @@ -name: MoviePilot Release -on: - workflow_dispatch: - push: - branches: - - main - paths: - - version.py - -jobs: - build: - runs-on: ubuntu-latest - name: Build Docker Image - steps: - - - name: Checkout - uses: actions/checkout@v4 - - - - name: Release Version - id: release_version - run: | - app_version=$(cat version.py |sed -ne "s/APP_VERSION\s=\s'v\(.*\)'/\1/gp") - echo "app_version=$app_version" >> $GITHUB_ENV - - - - name: Generate Release - uses: actions/create-release@latest - with: - tag_name: v${{ env.app_version }} - release_name: v${{ env.app_version }} - body: ${{ github.event.commits[0].message }} - draft: false - prerelease: false - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} From a96b8a4e071853359a0267096d27deb8f7862560 Mon Sep 17 00:00:00 2001 From: jxxghp Date: Mon, 9 Oct 2023 19:37:49 +0800 Subject: [PATCH 08/18] fix build --- .github/workflows/build-windows.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build-windows.yml b/.github/workflows/build-windows.yml index 8aac3e3f..ec8f3ac9 100644 --- a/.github/workflows/build-windows.yml +++ b/.github/workflows/build-windows.yml @@ -17,8 +17,8 @@ jobs: - name: Release Version id: release_version run: | - app_version=$(cat version.py |sed -ne "s/APP_VERSION\s=\s'v\(.*\)'/\1/gp") - echo "app_version=$app_version" >> $GITHUB_ENV + $app_version = Select-String -Path "version.py" -Pattern "APP_VERSION\s=\s'v(.*)'" | ForEach-Object { $_.Matches.Groups[1].Value } + $env:GITHUB_ENV += "app_version=$app_version" - name: Generate Release id: generate_release From c37e02009f548dd4cb8000533f4c8382688198d4 Mon Sep 17 00:00:00 2001 From: jxxghp Date: Mon, 9 Oct 2023 19:39:19 +0800 Subject: [PATCH 09/18] fix build --- .github/workflows/build-windows.yml | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/.github/workflows/build-windows.yml b/.github/workflows/build-windows.yml index ec8f3ac9..591456c8 100644 --- a/.github/workflows/build-windows.yml +++ b/.github/workflows/build-windows.yml @@ -20,18 +20,6 @@ jobs: $app_version = Select-String -Path "version.py" -Pattern "APP_VERSION\s=\s'v(.*)'" | ForEach-Object { $_.Matches.Groups[1].Value } $env:GITHUB_ENV += "app_version=$app_version" - - name: Generate Release - id: generate_release - uses: actions/create-release@latest - with: - tag_name: v${{ env.app_version }} - release_name: v${{ env.app_version }} - body: ${{ github.event.commits[0].message }} - draft: false - prerelease: false - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - name: Init Python 3.11.4 uses: actions/setup-python@v4 with: @@ -55,6 +43,18 @@ jobs: name: windows path: dist/MoviePilot.exe + - name: Generate Release + id: generate_release + uses: actions/create-release@latest + with: + tag_name: v${{ env.app_version }} + release_name: v${{ env.app_version }} + body: ${{ github.event.commits[0].message }} + draft: false + prerelease: false + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + - name: Upload Release Asset uses: dwenegar/upload-release-assets@v1 env: From de427fd7a98413bad08a0c7a69be581dea0cc485 Mon Sep 17 00:00:00 2001 From: jxxghp Date: Mon, 9 Oct 2023 20:14:54 +0800 Subject: [PATCH 10/18] fix --- .github/workflows/build-windows.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build-windows.yml b/.github/workflows/build-windows.yml index 591456c8..44ced5db 100644 --- a/.github/workflows/build-windows.yml +++ b/.github/workflows/build-windows.yml @@ -18,7 +18,7 @@ jobs: id: release_version run: | $app_version = Select-String -Path "version.py" -Pattern "APP_VERSION\s=\s'v(.*)'" | ForEach-Object { $_.Matches.Groups[1].Value } - $env:GITHUB_ENV += "app_version=$app_version" + echo "app_version=$app_version" >> $GITHUB_ENV - name: Init Python 3.11.4 uses: actions/setup-python@v4 From a03c76e211eaa7527d99213820f6400727e011e6 Mon Sep 17 00:00:00 2001 From: jxxghp Date: Mon, 9 Oct 2023 20:35:18 +0800 Subject: [PATCH 11/18] =?UTF-8?q?=E6=9B=B4=E6=96=B0=20build-windows.yml?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/build-windows.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build-windows.yml b/.github/workflows/build-windows.yml index 44ced5db..509122cd 100644 --- a/.github/workflows/build-windows.yml +++ b/.github/workflows/build-windows.yml @@ -18,7 +18,7 @@ jobs: id: release_version run: | $app_version = Select-String -Path "version.py" -Pattern "APP_VERSION\s=\s'v(.*)'" | ForEach-Object { $_.Matches.Groups[1].Value } - echo "app_version=$app_version" >> $GITHUB_ENV + echo app_version=%app_version% >> %GITHUB_ENV% - name: Init Python 3.11.4 uses: actions/setup-python@v4 From ecd53192dc3f45ce0526b3428d31ca828eab72d5 Mon Sep 17 00:00:00 2001 From: jxxghp Date: Mon, 9 Oct 2023 20:53:11 +0800 Subject: [PATCH 12/18] fix build --- .github/workflows/build-windows.yml | 65 ------------------------ .github/workflows/build.yml | 76 ++++++++++++++++++++++++++++- 2 files changed, 74 insertions(+), 67 deletions(-) delete mode 100644 .github/workflows/build-windows.yml diff --git a/.github/workflows/build-windows.yml b/.github/workflows/build-windows.yml deleted file mode 100644 index 509122cd..00000000 --- a/.github/workflows/build-windows.yml +++ /dev/null @@ -1,65 +0,0 @@ -name: MoviePilot Windows Builder -on: - workflow_dispatch: - push: - branches: - - main - paths: - - version.py - -jobs: - Windows-build: - runs-on: windows-latest - steps: - - name: Checkout - uses: actions/checkout@v4 - - - name: Release Version - id: release_version - run: | - $app_version = Select-String -Path "version.py" -Pattern "APP_VERSION\s=\s'v(.*)'" | ForEach-Object { $_.Matches.Groups[1].Value } - echo app_version=%app_version% >> %GITHUB_ENV% - - - name: Init Python 3.11.4 - uses: actions/setup-python@v4 - with: - python-version: '3.11.4' - - - name: Install Dependent Packages - run: | - python -m pip install --upgrade pip - pip install wheel pyinstaller - pip install -r requirements.txt - shell: pwsh - - - name: Pyinstaller - run: | - pyinstaller windows.spec - shell: pwsh - - - name: Upload Windows File - uses: actions/upload-artifact@v3 - with: - name: windows - path: dist/MoviePilot.exe - - - name: Generate Release - id: generate_release - uses: actions/create-release@latest - with: - tag_name: v${{ env.app_version }} - release_name: v${{ env.app_version }} - body: ${{ github.event.commits[0].message }} - draft: false - prerelease: false - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - - name: Upload Release Asset - uses: dwenegar/upload-release-assets@v1 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - with: - release_id: ${{ steps.generate_release.outputs.id }} - assets_path: | - dist/MoviePilot.exe diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 0b32b29d..cee43d5a 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -21,7 +21,7 @@ jobs: app_version=$(cat version.py |sed -ne "s/APP_VERSION\s=\s'v\(.*\)'/\1/gp") echo "app_version=$app_version" >> $GITHUB_ENV - - name: Docker meta + - name: Docker Meta id: meta uses: docker/metadata-action@v5 with: @@ -56,4 +56,76 @@ jobs: tags: ${{ steps.meta.outputs.tags }} labels: ${{ steps.meta.outputs.labels }} cache-from: type=gha, scope=${{ github.workflow }} - cache-to: type=gha, scope=${{ github.workflow }} \ No newline at end of file + cache-to: type=gha, scope=${{ github.workflow }} + + Windows-build: + runs-on: windows-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Init Python 3.11.4 + uses: actions/setup-python@v4 + with: + python-version: '3.11.4' + + - name: Install Dependent Packages + run: | + python -m pip install --upgrade pip + pip install wheel pyinstaller + pip install -r requirements.txt + shell: pwsh + + - name: Pyinstaller + run: | + pyinstaller windows.spec + shell: pwsh + + - name: Upload Windows File + uses: actions/upload-artifact@v3 + with: + name: windows + path: dist/MoviePilot.exe + + Create-release: + permissions: write-all + runs-on: ubuntu-latest + needs: [ Windows-build, Docker-build ] + steps: + - uses: actions/checkout@v2 + + - name: Release Version + id: release_version + run: | + app_version=$(cat version.py |sed -ne "s/APP_VERSION\s=\s'v\(.*\)'/\1/gp") + echo "app_version=$app_version" >> $GITHUB_ENV + + - name: Download Artifact + uses: actions/download-artifact@v3 + + - name: get release_informations + shell: bash + run: | + mkdir releases + mv ./windows/MoviePilot.exe ./releases/MoviePilot_v${{ env.app_version }}.exe + + - name: Create Release + id: create_release + uses: actions/create-release@latest + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + tag_name: v${{ env.app_version }} + release_name: v${{ env.app_version }} + body: ${{ github.event.commits[0].message }} + draft: false + prerelease: false + + - name: Upload Release Asset + uses: dwenegar/upload-release-assets@v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + release_id: ${{ steps.create_release.outputs.id }} + assets_path: | + ./releases/ \ No newline at end of file From a7cedde721669c9ec30667c3a1702cff5ac8b271 Mon Sep 17 00:00:00 2001 From: jxxghp Date: Mon, 9 Oct 2023 20:53:23 +0800 Subject: [PATCH 13/18] fix build --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index cee43d5a..d3064eb6 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -1,4 +1,4 @@ -name: MoviePilot Docker Builder +name: MoviePilot Builder on: workflow_dispatch: push: From 16077b33410e47f884002cbb2388b2d746c22f8e Mon Sep 17 00:00:00 2001 From: jxxghp Date: Mon, 9 Oct 2023 21:13:36 +0800 Subject: [PATCH 14/18] fix #769 --- .github/workflows/build.yml | 1 + app/plugins/invitessignin/__init__.py | 2 +- app/utils/system.py | 2 +- version.py | 2 +- 4 files changed, 4 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index d3064eb6..4887235d 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -60,6 +60,7 @@ jobs: Windows-build: runs-on: windows-latest + name: Build Windows Binary steps: - name: Checkout uses: actions/checkout@v4 diff --git a/app/plugins/invitessignin/__init__.py b/app/plugins/invitessignin/__init__.py index 1a8d0528..f8bd39fd 100644 --- a/app/plugins/invitessignin/__init__.py +++ b/app/plugins/invitessignin/__init__.py @@ -22,7 +22,7 @@ class InvitesSignin(_PluginBase): # 插件图标 plugin_icon = "invites.png" # 主题色 - plugin_color = "#4FB647" + plugin_color = "#FFFFFF" # 插件版本 plugin_version = "1.0" # 插件作者 diff --git a/app/utils/system.py b/app/utils/system.py index 10243801..47cbe5f1 100644 --- a/app/utils/system.py +++ b/app/utils/system.py @@ -97,7 +97,7 @@ class SystemUtils: """ try: # link到当前目录并改名 - tmp_path = (src.parent / dest.name).with_suffix(".mp") + tmp_path = src.parent / (dest.name + ".mp") tmp_path.hardlink_to(src) # 移动到目标目录 shutil.move(tmp_path, dest) diff --git a/version.py b/version.py index ae318a0f..e1d3dd99 100644 --- a/version.py +++ b/version.py @@ -1 +1 @@ -APP_VERSION = 'v1.2.9' +APP_VERSION = 'v1.3.0' From 0b44a91493a22aa76f2dca175e9c4713a736d785 Mon Sep 17 00:00:00 2001 From: jxxghp Date: Mon, 9 Oct 2023 21:33:53 +0800 Subject: [PATCH 15/18] fix README.md --- README.md | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 2982c9a6..bb709804 100644 --- a/README.md +++ b/README.md @@ -33,11 +33,19 @@ MoviePilot需要配套下载器和媒体服务器配合使用。 ### 4. **安装MoviePilot** -目前仅提供docker镜像,点击 [这里](https://hub.docker.com/r/jxxghp/moviepilot) 或执行命令: +- Docker镜像 -```shell -docker pull jxxghp/moviepilot:latest -``` + 点击 [这里](https://hub.docker.com/r/jxxghp/moviepilot) 或执行命令: + + ```shell + docker pull jxxghp/moviepilot:latest + ``` + +- Window + + 后端:https://github.com/jxxghp/MoviePilot-Frontend/releases + + 前端:https://github.com/jxxghp/MoviePilot-Frontend/releases ## 配置 From bf3e860a18ae3b2360b05b981ef46dd281233186 Mon Sep 17 00:00:00 2001 From: jxxghp Date: Mon, 9 Oct 2023 21:34:08 +0800 Subject: [PATCH 16/18] fix README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index bb709804..e056c770 100644 --- a/README.md +++ b/README.md @@ -43,7 +43,7 @@ MoviePilot需要配套下载器和媒体服务器配合使用。 - Window - 后端:https://github.com/jxxghp/MoviePilot-Frontend/releases + 后端:https://github.com/jxxghp/MoviePilot/releases 前端:https://github.com/jxxghp/MoviePilot-Frontend/releases From ae2f649aeee0d95c40b3d6f379ee43fac46c119f Mon Sep 17 00:00:00 2001 From: jxxghp Date: Mon, 9 Oct 2023 21:44:39 +0800 Subject: [PATCH 17/18] fix README.md --- README.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/README.md b/README.md index e056c770..1f1c96f6 100644 --- a/README.md +++ b/README.md @@ -4,8 +4,6 @@ # 仅用于学习交流使用,请勿在任何国内平台宣传该项目! -Docker:https://hub.docker.com/r/jxxghp/moviepilot - 发布频道:https://t.me/moviepilot_channel ## 主要特性 From 65b5219e45f22e7d74fcd860b862dd7c32d384c1 Mon Sep 17 00:00:00 2001 From: jxxghp Date: Tue, 10 Oct 2023 07:58:26 +0800 Subject: [PATCH 18/18] fix TZ --- Dockerfile | 1 + config/app.env | 2 -- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/Dockerfile b/Dockerfile index cb52713d..5da36ae6 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,6 +1,7 @@ FROM python:3.11.4-slim-bullseye ARG MOVIEPILOT_VERSION ENV LANG="C.UTF-8" \ + TZ="Asia/Shanghai" \ HOME="/moviepilot" \ TERM="xterm" \ PUID=0 \ diff --git a/config/app.env b/config/app.env index 4363817e..2a8ab338 100644 --- a/config/app.env +++ b/config/app.env @@ -5,8 +5,6 @@ #################################### # 基础设置 # #################################### -# 时区 -TZ=Asia/Shanghai # 【*】API监听地址 HOST=0.0.0.0 # 是否调试模式