plugin-jm-server 0.2.2__tar.gz → 0.2.3__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- plugin_jm_server-0.2.3/PKG-INFO +202 -0
- plugin_jm_server-0.2.3/README.md +166 -0
- {plugin_jm_server-0.2.2 → plugin_jm_server-0.2.3}/setup.py +3 -0
- plugin_jm_server-0.2.3/src/plugin_jm_server/__init__.py +3 -0
- plugin_jm_server-0.2.3/src/plugin_jm_server/__main__.py +5 -0
- plugin_jm_server-0.2.3/src/plugin_jm_server/cli.py +154 -0
- {plugin_jm_server-0.2.2 → plugin_jm_server-0.2.3}/src/plugin_jm_server/driver.py +10 -3
- plugin_jm_server-0.2.3/src/plugin_jm_server.egg-info/PKG-INFO +202 -0
- {plugin_jm_server-0.2.2 → plugin_jm_server-0.2.3}/src/plugin_jm_server.egg-info/SOURCES.txt +5 -1
- plugin_jm_server-0.2.3/src/plugin_jm_server.egg-info/entry_points.txt +2 -0
- plugin_jm_server-0.2.3/tests/test_cli.py +104 -0
- plugin_jm_server-0.2.2/PKG-INFO +0 -196
- plugin_jm_server-0.2.2/README.md +0 -160
- plugin_jm_server-0.2.2/src/plugin_jm_server/__init__.py +0 -3
- plugin_jm_server-0.2.2/src/plugin_jm_server.egg-info/PKG-INFO +0 -196
- {plugin_jm_server-0.2.2 → plugin_jm_server-0.2.3}/setup.cfg +0 -0
- {plugin_jm_server-0.2.2 → plugin_jm_server-0.2.3}/src/plugin_jm_server/app.py +0 -0
- {plugin_jm_server-0.2.2 → plugin_jm_server-0.2.3}/src/plugin_jm_server/files.py +0 -0
- {plugin_jm_server-0.2.2 → plugin_jm_server-0.2.3}/src/plugin_jm_server/message.py +0 -0
- {plugin_jm_server-0.2.2 → plugin_jm_server-0.2.3}/src/plugin_jm_server/static/css/all.min.css +0 -0
- {plugin_jm_server-0.2.2 → plugin_jm_server-0.2.3}/src/plugin_jm_server/static/css/bootstrap.css +0 -0
- {plugin_jm_server-0.2.2 → plugin_jm_server-0.2.3}/src/plugin_jm_server/static/css/download_error.css +0 -0
- {plugin_jm_server-0.2.2 → plugin_jm_server-0.2.3}/src/plugin_jm_server/static/css/h5/m_download_error.css +0 -0
- {plugin_jm_server-0.2.2 → plugin_jm_server-0.2.3}/src/plugin_jm_server/static/css/h5/m_index.css +0 -0
- {plugin_jm_server-0.2.2 → plugin_jm_server-0.2.3}/src/plugin_jm_server/static/css/h5/m_login.css +0 -0
- {plugin_jm_server-0.2.2 → plugin_jm_server-0.2.3}/src/plugin_jm_server/static/css/h5/m_message.css +0 -0
- {plugin_jm_server-0.2.2 → plugin_jm_server-0.2.3}/src/plugin_jm_server/static/css/h5/m_upload.css +0 -0
- {plugin_jm_server-0.2.2 → plugin_jm_server-0.2.3}/src/plugin_jm_server/static/css/h5/normalize.css +0 -0
- {plugin_jm_server-0.2.2 → plugin_jm_server-0.2.3}/src/plugin_jm_server/static/css/index.css +0 -0
- {plugin_jm_server-0.2.2 → plugin_jm_server-0.2.3}/src/plugin_jm_server/static/css/index_spa.css +0 -0
- {plugin_jm_server-0.2.2 → plugin_jm_server-0.2.3}/src/plugin_jm_server/static/css/login.css +0 -0
- {plugin_jm_server-0.2.2 → plugin_jm_server-0.2.3}/src/plugin_jm_server/static/css/message.css +0 -0
- {plugin_jm_server-0.2.2 → plugin_jm_server-0.2.3}/src/plugin_jm_server/static/css/style_photo.css +0 -0
- {plugin_jm_server-0.2.2 → plugin_jm_server-0.2.3}/src/plugin_jm_server/static/css/upload.css +0 -0
- {plugin_jm_server-0.2.2 → plugin_jm_server-0.2.3}/src/plugin_jm_server/static/img/bg.jpg +0 -0
- {plugin_jm_server-0.2.2 → plugin_jm_server-0.2.3}/src/plugin_jm_server/static/img/m_bg.jpeg +0 -0
- {plugin_jm_server-0.2.2 → plugin_jm_server-0.2.3}/src/plugin_jm_server/static/js/common.js +0 -0
- {plugin_jm_server-0.2.2 → plugin_jm_server-0.2.3}/src/plugin_jm_server/static/js/h5/m_index.js +0 -0
- {plugin_jm_server-0.2.2 → plugin_jm_server-0.2.3}/src/plugin_jm_server/static/js/h5/m_upload.js +0 -0
- {plugin_jm_server-0.2.2 → plugin_jm_server-0.2.3}/src/plugin_jm_server/static/js/index.js +0 -0
- {plugin_jm_server-0.2.2 → plugin_jm_server-0.2.3}/src/plugin_jm_server/static/js/index_spa.js +0 -0
- {plugin_jm_server-0.2.2 → plugin_jm_server-0.2.3}/src/plugin_jm_server/static/js/jquery-3.7.1.min.js +0 -0
- {plugin_jm_server-0.2.2 → plugin_jm_server-0.2.3}/src/plugin_jm_server/static/js/jquery.album-0.2.js +0 -0
- {plugin_jm_server-0.2.2 → plugin_jm_server-0.2.3}/src/plugin_jm_server/static/js/jquery.lazyload-2.0.js +0 -0
- {plugin_jm_server-0.2.2 → plugin_jm_server-0.2.3}/src/plugin_jm_server/static/js/jquery.photo-0.3.js +0 -0
- {plugin_jm_server-0.2.2 → plugin_jm_server-0.2.3}/src/plugin_jm_server/static/js/message.js +0 -0
- {plugin_jm_server-0.2.2 → plugin_jm_server-0.2.3}/src/plugin_jm_server/static/js/upload.js +0 -0
- {plugin_jm_server-0.2.2 → plugin_jm_server-0.2.3}/src/plugin_jm_server/static/webfonts/fa-regular-400.woff2 +0 -0
- {plugin_jm_server-0.2.2 → plugin_jm_server-0.2.3}/src/plugin_jm_server/static/webfonts/fa-solid-900.woff2 +0 -0
- {plugin_jm_server-0.2.2 → plugin_jm_server-0.2.3}/src/plugin_jm_server/templates/download_error.html +0 -0
- {plugin_jm_server-0.2.2 → plugin_jm_server-0.2.3}/src/plugin_jm_server/templates/index.html +0 -0
- {plugin_jm_server-0.2.2 → plugin_jm_server-0.2.3}/src/plugin_jm_server/templates/index_spa.html +0 -0
- {plugin_jm_server-0.2.2 → plugin_jm_server-0.2.3}/src/plugin_jm_server/templates/jm_view.html +0 -0
- {plugin_jm_server-0.2.2 → plugin_jm_server-0.2.3}/src/plugin_jm_server/templates/login.html +0 -0
- {plugin_jm_server-0.2.2 → plugin_jm_server-0.2.3}/src/plugin_jm_server/templates/m_download_error.html +0 -0
- {plugin_jm_server-0.2.2 → plugin_jm_server-0.2.3}/src/plugin_jm_server/templates/m_index.html +0 -0
- {plugin_jm_server-0.2.2 → plugin_jm_server-0.2.3}/src/plugin_jm_server/templates/m_jm_view.html +0 -0
- {plugin_jm_server-0.2.2 → plugin_jm_server-0.2.3}/src/plugin_jm_server/templates/m_login.html +0 -0
- {plugin_jm_server-0.2.2 → plugin_jm_server-0.2.3}/src/plugin_jm_server/templates/m_message.html +0 -0
- {plugin_jm_server-0.2.2 → plugin_jm_server-0.2.3}/src/plugin_jm_server/templates/m_upload.html +0 -0
- {plugin_jm_server-0.2.2 → plugin_jm_server-0.2.3}/src/plugin_jm_server/templates/message.html +0 -0
- {plugin_jm_server-0.2.2 → plugin_jm_server-0.2.3}/src/plugin_jm_server/templates/upload.html +0 -0
- {plugin_jm_server-0.2.2 → plugin_jm_server-0.2.3}/src/plugin_jm_server.egg-info/dependency_links.txt +0 -0
- {plugin_jm_server-0.2.2 → plugin_jm_server-0.2.3}/src/plugin_jm_server.egg-info/requires.txt +0 -0
- {plugin_jm_server-0.2.2 → plugin_jm_server-0.2.3}/src/plugin_jm_server.egg-info/top_level.txt +0 -0
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: plugin_jm_server
|
|
3
|
+
Version: 0.2.3
|
|
4
|
+
Summary: plugin_jm_server, a plugin for jmcomic that can be used to view comics in a web browser.
|
|
5
|
+
Home-page: https://github.com/hect0x7/plugin-jm-server
|
|
6
|
+
Author: hect0x7
|
|
7
|
+
Author-email: 93357912+hect0x7@users.noreply.github.com
|
|
8
|
+
Keywords: python,jmcomic,18comic,禁漫天堂,NSFW
|
|
9
|
+
Classifier: Development Status :: 4 - Beta
|
|
10
|
+
Classifier: Intended Audience :: Developers
|
|
11
|
+
Classifier: Programming Language :: Python :: 3.7
|
|
12
|
+
Classifier: Programming Language :: Python :: 3.8
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
17
|
+
Classifier: Operating System :: MacOS
|
|
18
|
+
Classifier: Operating System :: POSIX :: Linux
|
|
19
|
+
Classifier: Operating System :: Microsoft :: Windows
|
|
20
|
+
Requires-Python: >=3.7
|
|
21
|
+
Description-Content-Type: text/markdown
|
|
22
|
+
Requires-Dist: jmcomic
|
|
23
|
+
Requires-Dist: flask
|
|
24
|
+
Requires-Dist: psutil
|
|
25
|
+
Requires-Dist: cryptography
|
|
26
|
+
Dynamic: author
|
|
27
|
+
Dynamic: author-email
|
|
28
|
+
Dynamic: classifier
|
|
29
|
+
Dynamic: description
|
|
30
|
+
Dynamic: description-content-type
|
|
31
|
+
Dynamic: home-page
|
|
32
|
+
Dynamic: keywords
|
|
33
|
+
Dynamic: requires-dist
|
|
34
|
+
Dynamic: requires-python
|
|
35
|
+
Dynamic: summary
|
|
36
|
+
|
|
37
|
+
<!-- 顶部标题 & 统计徽章 -->
|
|
38
|
+
<div align="center">
|
|
39
|
+
<img src="images/logo.png" width="180" alt="plugin-jm-server logo">
|
|
40
|
+
<h1 style="margin-top: 15px" align="center">plugin-jm-server</h1>
|
|
41
|
+
|
|
42
|
+
<p align="center">
|
|
43
|
+
<strong>“离线版”禁漫天堂,你的纯本地 离线看本神器!</strong>
|
|
44
|
+
</p>
|
|
45
|
+
|
|
46
|
+
[](https://github.com/hect0x7)
|
|
47
|
+
[](https://github.com/hect0x7/plugin-jm-server/stargazers)
|
|
48
|
+
[](https://github.com/hect0x7/plugin-jm-server/forks)
|
|
49
|
+
[](https://pypi.org/project/plugin-jm-server/)
|
|
50
|
+
[](https://pepy.tech/projects/plugin-jm-server)
|
|
51
|
+
[](https://github.com/hect0x7/plugin-jm-server)
|
|
52
|
+
|
|
53
|
+
</div>
|
|
54
|
+
|
|
55
|
+
> 该项目会在你的电脑上启动一个**本地文件服务器**。你可以直接在浏览器(手机或电脑)中打开它,它会把本地文件夹里的图片转换成类似“禁漫天堂”的章节观看页面。
|
|
56
|
+
>
|
|
57
|
+
> **核心优势**:
|
|
58
|
+
> - 支持各种强大的浏览器插件和脚本,例如[双页阅读插件](https://sleazyfork.org/zh-CN/scripts/374903-comicread)。
|
|
59
|
+
> - 一键开启局域网共享,电脑下载,躺在床上用手机看。
|
|
60
|
+
|
|
61
|
+

|
|
62
|
+
|
|
63
|
+
---
|
|
64
|
+
|
|
65
|
+
## 🌟 功能与界面展示
|
|
66
|
+
|
|
67
|
+
本项目不仅提供了简单的文件浏览,还专为漫画阅读进行了深度优化:
|
|
68
|
+
|
|
69
|
+
### 1. 智能资源管理(文件夹浏览页)
|
|
70
|
+
- **路径导航**:输入框自动补全路径,快速定位。
|
|
71
|
+
- **封面预览**:鼠标悬停在文件夹上,自动展示首张图片作为封面。
|
|
72
|
+
- **书签收藏**:将常看目录加入左侧书签,方便下次访问。
|
|
73
|
+
|
|
74
|
+

|
|
75
|
+
*(电脑端:文件夹与看本二合一模式)* 
|
|
76
|
+
*(手机端:文件夹列表)* 
|
|
77
|
+
|
|
78
|
+
### 2. 沉浸式阅读体验(看本模式)
|
|
79
|
+
- **懒加载极速浏览**:哪怕一个章节有几百张高清大图,也能秒开且不卡顿。
|
|
80
|
+
- **多端适配**:无论是在宽屏显示器还是手机触摸屏上,都有最舒适的阅读排版。
|
|
81
|
+
- **快捷交互**:支持键盘翻页、浮动工具栏快速回到顶部等。
|
|
82
|
+
|
|
83
|
+
*(电脑端:看本模式)* 
|
|
84
|
+
*(手机端:看本模式)* 
|
|
85
|
+
|
|
86
|
+
### 3. 局域网消息与隐私保护
|
|
87
|
+
- **消息中心**:电脑和手机在局域网内可互传文本消息,实时弹窗提醒(v0.2.2+ 新功能)。
|
|
88
|
+
- **密码验证**:支持设置访问密码,防止同处局域网的其他室友/家人偷看!
|
|
89
|
+
|
|
90
|
+
*(局域网消息界面)* 
|
|
91
|
+
*(登录密码验证)* 
|
|
92
|
+
|
|
93
|
+
---
|
|
94
|
+
|
|
95
|
+
## 🚀 小白快速上手指南
|
|
96
|
+
|
|
97
|
+
如果你不懂编程,请严格按照以下两步操作即可:
|
|
98
|
+
|
|
99
|
+
### 第一步:环境准备
|
|
100
|
+
本项目基于 Python 开发,因此你的电脑必须先安装 Python。
|
|
101
|
+
- 请前往 [Python 官网](https://www.python.org/downloads/) 下载并安装最新版 Python(安装时请务必勾选 `Add Python to PATH`)。
|
|
102
|
+
|
|
103
|
+
### 第二步:一键安装与启动
|
|
104
|
+
打开你电脑的**命令行终端**(Windows 下按 `Win+R` 输入 `cmd`,Mac 下打开“终端”APP),复制并执行下面这行命令:
|
|
105
|
+
|
|
106
|
+
```shell
|
|
107
|
+
pip install plugin_jm_server && jms
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
> **提示**:这行命令会帮你自动下载安装必要的组件,并以默认配置(分享当前所在目录、端口80)启动服务器。
|
|
111
|
+
|
|
112
|
+
**启动成功后怎么用?**
|
|
113
|
+
终端里会打印出两行地址,例如:
|
|
114
|
+
- 本机访问:`http://127.0.0.1:80`
|
|
115
|
+
- 局域网访问:`http://192.168.1.100:80`
|
|
116
|
+
|
|
117
|
+
你只需要在电脑的浏览器里打开第一个地址,或者在连着同一个 WiFi 的手机浏览器里打开第二个地址,就可以开始看漫画了!
|
|
118
|
+
|
|
119
|
+
> **提示**:如果在终端没看清局域网地址也没关系,当你用电脑打开本机地址后,**网页的主页顶部也会直接显示并智能识别当前的局域网地址**,你可以一键复制发给手机直接访问。
|
|
120
|
+
|
|
121
|
+
---
|
|
122
|
+
|
|
123
|
+
## ⚙️ 进阶使用(针对有经验的用户)
|
|
124
|
+
|
|
125
|
+
安装后系统会注册 `jms` 命令,无需写代码即可通过丰富的参数进行个性化启动:
|
|
126
|
+
|
|
127
|
+
```shell
|
|
128
|
+
# 共享指定目录 ~/comics,并使用 8080 端口(高位端口无需管理员权限)
|
|
129
|
+
jms ~/comics -p 8080
|
|
130
|
+
|
|
131
|
+
# 设置登录密码为 123,并启用 HTTPS
|
|
132
|
+
jms ~/comics -P 123 -s
|
|
133
|
+
|
|
134
|
+
# 仅允许指定 IP 的设备访问
|
|
135
|
+
jms ~/comics --ip-whitelist 192.168.1.10,192.168.1.11
|
|
136
|
+
|
|
137
|
+
# 加载 jmcomic 配置开启在线下载
|
|
138
|
+
jms ~/comics -o op.yml
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
**全部参数说明(可通过 `jms -h` 查看):**
|
|
142
|
+
| 参数 | 说明 | 默认值 |
|
|
143
|
+
| --- | --- | --- |
|
|
144
|
+
| `path` | 要共享的根目录(位置参数) | 当前目录 |
|
|
145
|
+
| `-P, --password` | 登录密码,空表示免密 | 空 |
|
|
146
|
+
| `-H, --host` | 监听地址 | `0.0.0.0` |
|
|
147
|
+
| `-p, --port` | 监听端口 | `80` |
|
|
148
|
+
| `-s, --ssl` | 启用 HTTPS(adhoc 自签名) | 关闭 |
|
|
149
|
+
| `-o, --option` | [jmcomic](https://github.com/hect0x7/JMComic-Crawler-Python) 配置文件路径,开启在线下载 | 无 |
|
|
150
|
+
| `--ip-whitelist` | IP 白名单,逗号分隔 | 不限制 |
|
|
151
|
+
| `--current-path` | 初始当前路径 | 同 `path` |
|
|
152
|
+
| `-e, --env` | 设置环境变量 `KEY=VALUE`,可重复 | 无 |
|
|
153
|
+
| `--debug` | 开启 Flask debug 模式 | 关闭 |
|
|
154
|
+
|
|
155
|
+
> 注:如果你在 Linux/macOS 上启动报错没有权限,是因为绑定默认的 80 端口需要管理员权限。建议加上 `-p 8080` 参数改用其他端口。
|
|
156
|
+
|
|
157
|
+
---
|
|
158
|
+
|
|
159
|
+
## 👨💻 开发者专属区域
|
|
160
|
+
|
|
161
|
+
如果你想在自己的 Python 脚本中集成或二次开发该服务,可以通过代码进行调用。
|
|
162
|
+
|
|
163
|
+
### 1. HTTP / HTTPS 原生调用
|
|
164
|
+
```python
|
|
165
|
+
from plugin_jm_server import *
|
|
166
|
+
|
|
167
|
+
# 启动 HTTP 服务
|
|
168
|
+
server = JmServer('D:/', 'password')
|
|
169
|
+
server.run(host='0.0.0.0', port=80)
|
|
170
|
+
|
|
171
|
+
# 启动 HTTPS 服务 (需要安装 cryptography)
|
|
172
|
+
server.run(host='0.0.0.0', port=443, ssl_context='adhoc')
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
### 2. 作为 jmcomic 的插件集成
|
|
176
|
+
你可以在 `jmcomic` 的 `op.yml` 配置文件中配置它:
|
|
177
|
+
```yml
|
|
178
|
+
plugins:
|
|
179
|
+
after_init:
|
|
180
|
+
- plugin: jm_server
|
|
181
|
+
kwargs:
|
|
182
|
+
password: ''
|
|
183
|
+
```
|
|
184
|
+
对应的启动脚本注意事项:
|
|
185
|
+
```python
|
|
186
|
+
from jmcomic import *
|
|
187
|
+
|
|
188
|
+
op = create_option('op.yml')
|
|
189
|
+
op.download_album(123)
|
|
190
|
+
|
|
191
|
+
# 注意:虽然爬虫主线程执行完毕,但 Web 服务器线程仍在运行中。
|
|
192
|
+
# 需要用户手动按 Ctrl+C 退出。
|
|
193
|
+
# Python 3.12+ 特别注意:必须插入下面这行代码,Web 服务器才能继续处理请求!
|
|
194
|
+
op.wait_all_plugins_finish()
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
---
|
|
198
|
+
|
|
199
|
+
## 💡 想法起源
|
|
200
|
+
|
|
201
|
+
- 想法起源:https://github.com/hect0x7/JMComic-Crawler-Python/issues/192
|
|
202
|
+
- UI 与部分基础架构参考:https://github.com/AiCorein/Flask-Files-Server
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
<!-- 顶部标题 & 统计徽章 -->
|
|
2
|
+
<div align="center">
|
|
3
|
+
<img src="images/logo.png" width="180" alt="plugin-jm-server logo">
|
|
4
|
+
<h1 style="margin-top: 15px" align="center">plugin-jm-server</h1>
|
|
5
|
+
|
|
6
|
+
<p align="center">
|
|
7
|
+
<strong>“离线版”禁漫天堂,你的纯本地 离线看本神器!</strong>
|
|
8
|
+
</p>
|
|
9
|
+
|
|
10
|
+
[](https://github.com/hect0x7)
|
|
11
|
+
[](https://github.com/hect0x7/plugin-jm-server/stargazers)
|
|
12
|
+
[](https://github.com/hect0x7/plugin-jm-server/forks)
|
|
13
|
+
[](https://pypi.org/project/plugin-jm-server/)
|
|
14
|
+
[](https://pepy.tech/projects/plugin-jm-server)
|
|
15
|
+
[](https://github.com/hect0x7/plugin-jm-server)
|
|
16
|
+
|
|
17
|
+
</div>
|
|
18
|
+
|
|
19
|
+
> 该项目会在你的电脑上启动一个**本地文件服务器**。你可以直接在浏览器(手机或电脑)中打开它,它会把本地文件夹里的图片转换成类似“禁漫天堂”的章节观看页面。
|
|
20
|
+
>
|
|
21
|
+
> **核心优势**:
|
|
22
|
+
> - 支持各种强大的浏览器插件和脚本,例如[双页阅读插件](https://sleazyfork.org/zh-CN/scripts/374903-comicread)。
|
|
23
|
+
> - 一键开启局域网共享,电脑下载,躺在床上用手机看。
|
|
24
|
+
|
|
25
|
+

|
|
26
|
+
|
|
27
|
+
---
|
|
28
|
+
|
|
29
|
+
## 🌟 功能与界面展示
|
|
30
|
+
|
|
31
|
+
本项目不仅提供了简单的文件浏览,还专为漫画阅读进行了深度优化:
|
|
32
|
+
|
|
33
|
+
### 1. 智能资源管理(文件夹浏览页)
|
|
34
|
+
- **路径导航**:输入框自动补全路径,快速定位。
|
|
35
|
+
- **封面预览**:鼠标悬停在文件夹上,自动展示首张图片作为封面。
|
|
36
|
+
- **书签收藏**:将常看目录加入左侧书签,方便下次访问。
|
|
37
|
+
|
|
38
|
+

|
|
39
|
+
*(电脑端:文件夹与看本二合一模式)* 
|
|
40
|
+
*(手机端:文件夹列表)* 
|
|
41
|
+
|
|
42
|
+
### 2. 沉浸式阅读体验(看本模式)
|
|
43
|
+
- **懒加载极速浏览**:哪怕一个章节有几百张高清大图,也能秒开且不卡顿。
|
|
44
|
+
- **多端适配**:无论是在宽屏显示器还是手机触摸屏上,都有最舒适的阅读排版。
|
|
45
|
+
- **快捷交互**:支持键盘翻页、浮动工具栏快速回到顶部等。
|
|
46
|
+
|
|
47
|
+
*(电脑端:看本模式)* 
|
|
48
|
+
*(手机端:看本模式)* 
|
|
49
|
+
|
|
50
|
+
### 3. 局域网消息与隐私保护
|
|
51
|
+
- **消息中心**:电脑和手机在局域网内可互传文本消息,实时弹窗提醒(v0.2.2+ 新功能)。
|
|
52
|
+
- **密码验证**:支持设置访问密码,防止同处局域网的其他室友/家人偷看!
|
|
53
|
+
|
|
54
|
+
*(局域网消息界面)* 
|
|
55
|
+
*(登录密码验证)* 
|
|
56
|
+
|
|
57
|
+
---
|
|
58
|
+
|
|
59
|
+
## 🚀 小白快速上手指南
|
|
60
|
+
|
|
61
|
+
如果你不懂编程,请严格按照以下两步操作即可:
|
|
62
|
+
|
|
63
|
+
### 第一步:环境准备
|
|
64
|
+
本项目基于 Python 开发,因此你的电脑必须先安装 Python。
|
|
65
|
+
- 请前往 [Python 官网](https://www.python.org/downloads/) 下载并安装最新版 Python(安装时请务必勾选 `Add Python to PATH`)。
|
|
66
|
+
|
|
67
|
+
### 第二步:一键安装与启动
|
|
68
|
+
打开你电脑的**命令行终端**(Windows 下按 `Win+R` 输入 `cmd`,Mac 下打开“终端”APP),复制并执行下面这行命令:
|
|
69
|
+
|
|
70
|
+
```shell
|
|
71
|
+
pip install plugin_jm_server && jms
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
> **提示**:这行命令会帮你自动下载安装必要的组件,并以默认配置(分享当前所在目录、端口80)启动服务器。
|
|
75
|
+
|
|
76
|
+
**启动成功后怎么用?**
|
|
77
|
+
终端里会打印出两行地址,例如:
|
|
78
|
+
- 本机访问:`http://127.0.0.1:80`
|
|
79
|
+
- 局域网访问:`http://192.168.1.100:80`
|
|
80
|
+
|
|
81
|
+
你只需要在电脑的浏览器里打开第一个地址,或者在连着同一个 WiFi 的手机浏览器里打开第二个地址,就可以开始看漫画了!
|
|
82
|
+
|
|
83
|
+
> **提示**:如果在终端没看清局域网地址也没关系,当你用电脑打开本机地址后,**网页的主页顶部也会直接显示并智能识别当前的局域网地址**,你可以一键复制发给手机直接访问。
|
|
84
|
+
|
|
85
|
+
---
|
|
86
|
+
|
|
87
|
+
## ⚙️ 进阶使用(针对有经验的用户)
|
|
88
|
+
|
|
89
|
+
安装后系统会注册 `jms` 命令,无需写代码即可通过丰富的参数进行个性化启动:
|
|
90
|
+
|
|
91
|
+
```shell
|
|
92
|
+
# 共享指定目录 ~/comics,并使用 8080 端口(高位端口无需管理员权限)
|
|
93
|
+
jms ~/comics -p 8080
|
|
94
|
+
|
|
95
|
+
# 设置登录密码为 123,并启用 HTTPS
|
|
96
|
+
jms ~/comics -P 123 -s
|
|
97
|
+
|
|
98
|
+
# 仅允许指定 IP 的设备访问
|
|
99
|
+
jms ~/comics --ip-whitelist 192.168.1.10,192.168.1.11
|
|
100
|
+
|
|
101
|
+
# 加载 jmcomic 配置开启在线下载
|
|
102
|
+
jms ~/comics -o op.yml
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
**全部参数说明(可通过 `jms -h` 查看):**
|
|
106
|
+
| 参数 | 说明 | 默认值 |
|
|
107
|
+
| --- | --- | --- |
|
|
108
|
+
| `path` | 要共享的根目录(位置参数) | 当前目录 |
|
|
109
|
+
| `-P, --password` | 登录密码,空表示免密 | 空 |
|
|
110
|
+
| `-H, --host` | 监听地址 | `0.0.0.0` |
|
|
111
|
+
| `-p, --port` | 监听端口 | `80` |
|
|
112
|
+
| `-s, --ssl` | 启用 HTTPS(adhoc 自签名) | 关闭 |
|
|
113
|
+
| `-o, --option` | [jmcomic](https://github.com/hect0x7/JMComic-Crawler-Python) 配置文件路径,开启在线下载 | 无 |
|
|
114
|
+
| `--ip-whitelist` | IP 白名单,逗号分隔 | 不限制 |
|
|
115
|
+
| `--current-path` | 初始当前路径 | 同 `path` |
|
|
116
|
+
| `-e, --env` | 设置环境变量 `KEY=VALUE`,可重复 | 无 |
|
|
117
|
+
| `--debug` | 开启 Flask debug 模式 | 关闭 |
|
|
118
|
+
|
|
119
|
+
> 注:如果你在 Linux/macOS 上启动报错没有权限,是因为绑定默认的 80 端口需要管理员权限。建议加上 `-p 8080` 参数改用其他端口。
|
|
120
|
+
|
|
121
|
+
---
|
|
122
|
+
|
|
123
|
+
## 👨💻 开发者专属区域
|
|
124
|
+
|
|
125
|
+
如果你想在自己的 Python 脚本中集成或二次开发该服务,可以通过代码进行调用。
|
|
126
|
+
|
|
127
|
+
### 1. HTTP / HTTPS 原生调用
|
|
128
|
+
```python
|
|
129
|
+
from plugin_jm_server import *
|
|
130
|
+
|
|
131
|
+
# 启动 HTTP 服务
|
|
132
|
+
server = JmServer('D:/', 'password')
|
|
133
|
+
server.run(host='0.0.0.0', port=80)
|
|
134
|
+
|
|
135
|
+
# 启动 HTTPS 服务 (需要安装 cryptography)
|
|
136
|
+
server.run(host='0.0.0.0', port=443, ssl_context='adhoc')
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
### 2. 作为 jmcomic 的插件集成
|
|
140
|
+
你可以在 `jmcomic` 的 `op.yml` 配置文件中配置它:
|
|
141
|
+
```yml
|
|
142
|
+
plugins:
|
|
143
|
+
after_init:
|
|
144
|
+
- plugin: jm_server
|
|
145
|
+
kwargs:
|
|
146
|
+
password: ''
|
|
147
|
+
```
|
|
148
|
+
对应的启动脚本注意事项:
|
|
149
|
+
```python
|
|
150
|
+
from jmcomic import *
|
|
151
|
+
|
|
152
|
+
op = create_option('op.yml')
|
|
153
|
+
op.download_album(123)
|
|
154
|
+
|
|
155
|
+
# 注意:虽然爬虫主线程执行完毕,但 Web 服务器线程仍在运行中。
|
|
156
|
+
# 需要用户手动按 Ctrl+C 退出。
|
|
157
|
+
# Python 3.12+ 特别注意:必须插入下面这行代码,Web 服务器才能继续处理请求!
|
|
158
|
+
op.wait_all_plugins_finish()
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
---
|
|
162
|
+
|
|
163
|
+
## 💡 想法起源
|
|
164
|
+
|
|
165
|
+
- 想法起源:https://github.com/hect0x7/JMComic-Crawler-Python/issues/192
|
|
166
|
+
- UI 与部分基础架构参考:https://github.com/AiCorein/Flask-Files-Server
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
"""
|
|
2
|
+
命令行入口
|
|
3
|
+
|
|
4
|
+
让用户无需编写 Python 代码即可启动服务器,例如:
|
|
5
|
+
|
|
6
|
+
jms ~/comics --password 123 --port 8080
|
|
7
|
+
|
|
8
|
+
等价于:
|
|
9
|
+
|
|
10
|
+
from plugin_jm_server import JmServer
|
|
11
|
+
JmServer('~/comics', '123').run(host='0.0.0.0', port=8080)
|
|
12
|
+
|
|
13
|
+
也支持 `python -m plugin_jm_server ...`(见 __main__.py)。
|
|
14
|
+
"""
|
|
15
|
+
import argparse
|
|
16
|
+
|
|
17
|
+
from . import __version__
|
|
18
|
+
from .app import JmServer
|
|
19
|
+
|
|
20
|
+
EPILOG = """\
|
|
21
|
+
示例:
|
|
22
|
+
jms # 共享当前目录, 端口 80, 免密登录
|
|
23
|
+
jms ~/comics -p 8080 # 共享 ~/comics, 端口 8080
|
|
24
|
+
jms ~/comics -P 123 -s # 设置密码并启用 HTTPS(自签名)
|
|
25
|
+
jms ~/comics -o op.yml # 加载 jmcomic 配置, 开启在线下载
|
|
26
|
+
jms D:/ --ip-whitelist 192.168.1.10,192.168.1.11
|
|
27
|
+
|
|
28
|
+
启动后用浏览器访问提示的局域网地址即可(手机与电脑需在同一局域网)。
|
|
29
|
+
"""
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def build_parser():
|
|
33
|
+
"""构造 argparse 解析器。单独抽出便于测试。"""
|
|
34
|
+
parser = argparse.ArgumentParser(
|
|
35
|
+
prog='jms',
|
|
36
|
+
description='“离线版”禁漫天堂:在本地启动文件服务器,用浏览器以禁漫章节模式查看图片。',
|
|
37
|
+
formatter_class=argparse.RawDescriptionHelpFormatter,
|
|
38
|
+
epilog=EPILOG,
|
|
39
|
+
)
|
|
40
|
+
parser.add_argument('path', nargs='?', default='.',
|
|
41
|
+
help='要共享的根目录(默认: 当前目录)')
|
|
42
|
+
parser.add_argument('-P', '--password', default='',
|
|
43
|
+
help='登录密码(默认: 空, 即免密登录)')
|
|
44
|
+
parser.add_argument('-H', '--host', default='0.0.0.0',
|
|
45
|
+
help='监听地址(默认: 0.0.0.0, 局域网可访问)')
|
|
46
|
+
parser.add_argument('-p', '--port', type=int, default=JmServer.DEFAULT_PORT,
|
|
47
|
+
help='监听端口(默认: %(default)s)')
|
|
48
|
+
parser.add_argument('-s', '--ssl', action='store_true',
|
|
49
|
+
help='启用 HTTPS(使用 adhoc 自签名证书, 需安装 cryptography)')
|
|
50
|
+
parser.add_argument('-o', '--option', metavar='OP_YML',
|
|
51
|
+
help='jmcomic 配置文件路径, 提供后开启在线下载功能')
|
|
52
|
+
parser.add_argument('--ip-whitelist', metavar='IP[,IP...]',
|
|
53
|
+
help='IP 白名单, 逗号分隔; 不在名单内的请求返回 404')
|
|
54
|
+
parser.add_argument('--current-path', metavar='PATH',
|
|
55
|
+
help='初始当前路径(默认与共享根目录相同)')
|
|
56
|
+
parser.add_argument('-e', '--env', action='append', metavar='KEY=VALUE',
|
|
57
|
+
help='设置环境变量, 可重复指定')
|
|
58
|
+
parser.add_argument('--debug', action='store_true',
|
|
59
|
+
help='开启 Flask debug 模式')
|
|
60
|
+
parser.add_argument('-v', '--version', action='version',
|
|
61
|
+
version='%(prog)s {}'.format(__version__))
|
|
62
|
+
return parser
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
def parse_env(env_list):
|
|
66
|
+
"""把 ['A=1', 'B=2'] 解析成 {'A': '1', 'B': '2'}。"""
|
|
67
|
+
env = {}
|
|
68
|
+
for item in env_list or []:
|
|
69
|
+
if '=' not in item:
|
|
70
|
+
raise ValueError('--env 格式应为 KEY=VALUE, 收到: {!r}'.format(item))
|
|
71
|
+
k, v = item.split('=', 1)
|
|
72
|
+
env[k] = v
|
|
73
|
+
return env
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
def parse_ip_whitelist(raw):
|
|
77
|
+
"""把 '1.1.1.1, 2.2.2.2' 解析成列表; 为空时返回 None(表示不限制)。"""
|
|
78
|
+
if not raw:
|
|
79
|
+
return None
|
|
80
|
+
return [ip.strip() for ip in raw.split(',') if ip.strip()] or None
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
def build_server(args):
|
|
84
|
+
"""根据解析后的 args 构造 JmServer(不启动)。抽出以便单测。"""
|
|
85
|
+
jm_option = None
|
|
86
|
+
if args.option:
|
|
87
|
+
import jmcomic
|
|
88
|
+
jm_option = jmcomic.create_option(args.option)
|
|
89
|
+
|
|
90
|
+
return JmServer(
|
|
91
|
+
args.path,
|
|
92
|
+
args.password,
|
|
93
|
+
jm_option=jm_option,
|
|
94
|
+
ip_whitelist=parse_ip_whitelist(args.ip_whitelist),
|
|
95
|
+
current_path=args.current_path,
|
|
96
|
+
env=parse_env(args.env),
|
|
97
|
+
# 传入 port, 首页据此拼出局域网访问地址 http://IP:PORT
|
|
98
|
+
port=args.port,
|
|
99
|
+
)
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
def build_run_kwargs(args):
|
|
103
|
+
"""把 args 映射为 JmServer.run() / Flask app.run() 的关键字参数。"""
|
|
104
|
+
kwargs = {'host': args.host, 'port': args.port}
|
|
105
|
+
if args.ssl:
|
|
106
|
+
kwargs['ssl_context'] = 'adhoc'
|
|
107
|
+
if args.debug:
|
|
108
|
+
kwargs['debug'] = True
|
|
109
|
+
return kwargs
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
def print_banner(args):
|
|
113
|
+
from .driver import get_lan_ip
|
|
114
|
+
scheme = 'https' if args.ssl else 'http'
|
|
115
|
+
lan_ip = get_lan_ip()
|
|
116
|
+
print('=' * 48)
|
|
117
|
+
print('plugin-jm-server v{} 已启动'.format(__version__))
|
|
118
|
+
print('共享目录 : {}'.format(args.path))
|
|
119
|
+
print('本机访问 : {}://127.0.0.1:{}'.format(scheme, args.port))
|
|
120
|
+
if args.host == '0.0.0.0':
|
|
121
|
+
print('局域网访问: {}://{}:{}'.format(scheme, lan_ip, args.port))
|
|
122
|
+
if not args.password:
|
|
123
|
+
print('提示 : 未设置密码, 任何人都能访问, 建议用 -P 设置密码')
|
|
124
|
+
print('按 Ctrl+C 停止服务')
|
|
125
|
+
print('=' * 48)
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
def main(argv=None):
|
|
129
|
+
parser = build_parser()
|
|
130
|
+
args = parser.parse_args(argv)
|
|
131
|
+
|
|
132
|
+
try:
|
|
133
|
+
server = build_server(args)
|
|
134
|
+
except Exception as e: # 配置/参数错误, 以非 0 退出并给出清晰提示
|
|
135
|
+
parser.error(str(e))
|
|
136
|
+
return # parser.error 已 exit, 此行仅为静态分析
|
|
137
|
+
|
|
138
|
+
run_kwargs = build_run_kwargs(args)
|
|
139
|
+
print_banner(args)
|
|
140
|
+
|
|
141
|
+
try:
|
|
142
|
+
server.run(**run_kwargs)
|
|
143
|
+
except PermissionError:
|
|
144
|
+
parser.exit(1, '\n端口 {} 需要管理员权限。请改用高位端口, 例如: jms {} -p 8080\n'
|
|
145
|
+
.format(args.port, args.path))
|
|
146
|
+
except OSError as e:
|
|
147
|
+
parser.exit(1, '\n启动失败(端口 {} 可能已被占用): {}\n请换一个端口, 例如 -p 8080\n'
|
|
148
|
+
.format(args.port, e))
|
|
149
|
+
except KeyboardInterrupt:
|
|
150
|
+
print('\n已停止。')
|
|
151
|
+
|
|
152
|
+
|
|
153
|
+
if __name__ == '__main__':
|
|
154
|
+
main()
|
|
@@ -55,6 +55,7 @@ def get_lan_ip():
|
|
|
55
55
|
'172.26.', '172.27.', '172.28.', '172.29.', '172.30.', '172.31.')
|
|
56
56
|
|
|
57
57
|
# 1. 优先寻找处于 up 状态且有私有 IP 的物理网卡
|
|
58
|
+
fallback_ip = None
|
|
58
59
|
for interface, snics in addrs.items():
|
|
59
60
|
# 跳过禁用的网卡
|
|
60
61
|
if interface in stats and not stats[interface].isup:
|
|
@@ -64,9 +65,15 @@ def get_lan_ip():
|
|
|
64
65
|
# 必须是 IPv4
|
|
65
66
|
if snic.family == socket.AF_INET:
|
|
66
67
|
ip = snic.address
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
68
|
+
if not ip.startswith('127.'):
|
|
69
|
+
if fallback_ip is None:
|
|
70
|
+
fallback_ip = ip
|
|
71
|
+
# 排除回环地址,且必须符合私有地址段
|
|
72
|
+
if any(ip.startswith(prefix) for prefix in private_prefixes):
|
|
73
|
+
return ip
|
|
74
|
+
|
|
75
|
+
if fallback_ip:
|
|
76
|
+
return fallback_ip
|
|
70
77
|
|
|
71
78
|
# 2. 如果没找到私有地址,尝试获取主机名的 IP
|
|
72
79
|
host_ip = socket.gethostbyname(socket.gethostname())
|