plugin-jm-server 0.1.23__tar.gz → 0.2.0__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.1.23 → plugin_jm_server-0.2.0}/PKG-INFO +45 -4
- {plugin_jm_server-0.1.23 → plugin_jm_server-0.2.0}/README.md +33 -2
- plugin_jm_server-0.2.0/src/plugin_jm_server/__init__.py +3 -0
- {plugin_jm_server-0.1.23 → plugin_jm_server-0.2.0}/src/plugin_jm_server/app.py +95 -7
- {plugin_jm_server-0.1.23 → plugin_jm_server-0.2.0}/src/plugin_jm_server/driver.py +6 -5
- plugin_jm_server-0.2.0/src/plugin_jm_server/files.py +170 -0
- plugin_jm_server-0.2.0/src/plugin_jm_server/static/css/index.css +729 -0
- plugin_jm_server-0.2.0/src/plugin_jm_server/static/css/index_spa.css +556 -0
- plugin_jm_server-0.2.0/src/plugin_jm_server/static/css/style_photo.css +1 -0
- plugin_jm_server-0.2.0/src/plugin_jm_server/static/img/bg.jpg +0 -0
- plugin_jm_server-0.2.0/src/plugin_jm_server/static/js/common.js +78 -0
- plugin_jm_server-0.2.0/src/plugin_jm_server/static/js/index.js +317 -0
- plugin_jm_server-0.2.0/src/plugin_jm_server/static/js/index_spa.js +612 -0
- plugin_jm_server-0.2.0/src/plugin_jm_server/static/js/jquery.lazyload-2.0.js +444 -0
- plugin_jm_server-0.2.0/src/plugin_jm_server/static/js/jquery.photo-0.3.js +427 -0
- plugin_jm_server-0.2.0/src/plugin_jm_server/templates/index.html +191 -0
- plugin_jm_server-0.2.0/src/plugin_jm_server/templates/index_spa.html +118 -0
- {plugin_jm_server-0.1.23 → plugin_jm_server-0.2.0}/src/plugin_jm_server/templates/jm_view.html +10 -3
- plugin_jm_server-0.2.0/src/plugin_jm_server/templates/m_index.html +187 -0
- {plugin_jm_server-0.1.23 → plugin_jm_server-0.2.0}/src/plugin_jm_server.egg-info/PKG-INFO +45 -4
- {plugin_jm_server-0.1.23 → plugin_jm_server-0.2.0}/src/plugin_jm_server.egg-info/SOURCES.txt +5 -0
- plugin_jm_server-0.1.23/src/plugin_jm_server/__init__.py +0 -3
- plugin_jm_server-0.1.23/src/plugin_jm_server/files.py +0 -119
- plugin_jm_server-0.1.23/src/plugin_jm_server/static/css/index.css +0 -200
- plugin_jm_server-0.1.23/src/plugin_jm_server/static/css/style_photo.css +0 -1
- plugin_jm_server-0.1.23/src/plugin_jm_server/static/img/bg.jpg +0 -0
- plugin_jm_server-0.1.23/src/plugin_jm_server/static/js/common.js +0 -49
- plugin_jm_server-0.1.23/src/plugin_jm_server/static/js/index.js +0 -95
- plugin_jm_server-0.1.23/src/plugin_jm_server/templates/index.html +0 -100
- plugin_jm_server-0.1.23/src/plugin_jm_server/templates/m_index.html +0 -92
- {plugin_jm_server-0.1.23 → plugin_jm_server-0.2.0}/setup.cfg +0 -0
- {plugin_jm_server-0.1.23 → plugin_jm_server-0.2.0}/setup.py +0 -0
- {plugin_jm_server-0.1.23 → plugin_jm_server-0.2.0}/src/plugin_jm_server/static/css/all.min.css +0 -0
- {plugin_jm_server-0.1.23 → plugin_jm_server-0.2.0}/src/plugin_jm_server/static/css/bootstrap.css +0 -0
- {plugin_jm_server-0.1.23 → plugin_jm_server-0.2.0}/src/plugin_jm_server/static/css/download_error.css +0 -0
- {plugin_jm_server-0.1.23 → plugin_jm_server-0.2.0}/src/plugin_jm_server/static/css/h5/m_download_error.css +0 -0
- {plugin_jm_server-0.1.23 → plugin_jm_server-0.2.0}/src/plugin_jm_server/static/css/h5/m_index.css +0 -0
- {plugin_jm_server-0.1.23 → plugin_jm_server-0.2.0}/src/plugin_jm_server/static/css/h5/m_login.css +0 -0
- {plugin_jm_server-0.1.23 → plugin_jm_server-0.2.0}/src/plugin_jm_server/static/css/h5/m_upload.css +0 -0
- {plugin_jm_server-0.1.23 → plugin_jm_server-0.2.0}/src/plugin_jm_server/static/css/h5/normalize.css +0 -0
- {plugin_jm_server-0.1.23 → plugin_jm_server-0.2.0}/src/plugin_jm_server/static/css/login.css +0 -0
- {plugin_jm_server-0.1.23 → plugin_jm_server-0.2.0}/src/plugin_jm_server/static/css/upload.css +0 -0
- {plugin_jm_server-0.1.23 → plugin_jm_server-0.2.0}/src/plugin_jm_server/static/img/m_bg.jpeg +0 -0
- {plugin_jm_server-0.1.23 → plugin_jm_server-0.2.0}/src/plugin_jm_server/static/js/h5/m_index.js +0 -0
- {plugin_jm_server-0.1.23 → plugin_jm_server-0.2.0}/src/plugin_jm_server/static/js/h5/m_upload.js +0 -0
- {plugin_jm_server-0.1.23 → plugin_jm_server-0.2.0}/src/plugin_jm_server/static/js/jquery-3.7.1.min.js +0 -0
- {plugin_jm_server-0.1.23 → plugin_jm_server-0.2.0}/src/plugin_jm_server/static/js/jquery.album-0.2.js +0 -0
- {plugin_jm_server-0.1.23 → plugin_jm_server-0.2.0}/src/plugin_jm_server/static/js/upload.js +0 -0
- {plugin_jm_server-0.1.23 → plugin_jm_server-0.2.0}/src/plugin_jm_server/static/webfonts/fa-regular-400.woff2 +0 -0
- {plugin_jm_server-0.1.23 → plugin_jm_server-0.2.0}/src/plugin_jm_server/static/webfonts/fa-solid-900.woff2 +0 -0
- {plugin_jm_server-0.1.23 → plugin_jm_server-0.2.0}/src/plugin_jm_server/templates/download_error.html +0 -0
- {plugin_jm_server-0.1.23 → plugin_jm_server-0.2.0}/src/plugin_jm_server/templates/login.html +0 -0
- {plugin_jm_server-0.1.23 → plugin_jm_server-0.2.0}/src/plugin_jm_server/templates/m_download_error.html +0 -0
- {plugin_jm_server-0.1.23 → plugin_jm_server-0.2.0}/src/plugin_jm_server/templates/m_jm_view.html +0 -0
- {plugin_jm_server-0.1.23 → plugin_jm_server-0.2.0}/src/plugin_jm_server/templates/m_login.html +0 -0
- {plugin_jm_server-0.1.23 → plugin_jm_server-0.2.0}/src/plugin_jm_server/templates/m_upload.html +0 -0
- {plugin_jm_server-0.1.23 → plugin_jm_server-0.2.0}/src/plugin_jm_server/templates/upload.html +0 -0
- {plugin_jm_server-0.1.23 → plugin_jm_server-0.2.0}/src/plugin_jm_server.egg-info/dependency_links.txt +0 -0
- {plugin_jm_server-0.1.23 → plugin_jm_server-0.2.0}/src/plugin_jm_server.egg-info/requires.txt +0 -0
- {plugin_jm_server-0.1.23 → plugin_jm_server-0.2.0}/src/plugin_jm_server.egg-info/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: plugin_jm_server
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.2.0
|
|
4
4
|
Summary: plugin_jm_server, a plugin for jmcomic that can be used to view comics in a web browser.
|
|
5
5
|
Home-page: https://github.com/hect0x7/plugin-jm-server
|
|
6
6
|
Author: hect0x7
|
|
@@ -23,9 +23,29 @@ Requires-Dist: jmcomic
|
|
|
23
23
|
Requires-Dist: flask
|
|
24
24
|
Requires-Dist: psutil
|
|
25
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
|
|
26
36
|
|
|
27
37
|
# plugin-jm-server
|
|
28
38
|
|
|
39
|
+
“离线版”禁漫天堂
|
|
40
|
+
|
|
41
|
+
该项目会在本地起一个`文件服务器`,支持用浏览器查看文件夹内的图片,界面模仿禁漫的章节观看页面,并适配手机端。
|
|
42
|
+
|
|
43
|
+
用浏览器的好处就是支持很多浏览器插件和脚本,例如:
|
|
44
|
+
|
|
45
|
+
* 双页阅读插件:https://sleazyfork.org/zh-CN/scripts/374903-comicread
|
|
46
|
+
|
|
47
|
+
# 想法起源
|
|
48
|
+
|
|
29
49
|
想法起源:https://github.com/hect0x7/JMComic-Crawler-Python/issues/192
|
|
30
50
|
|
|
31
51
|
基于原项目:https://github.com/AiCorein/Flask-Files-Server
|
|
@@ -33,9 +53,14 @@ Requires-Dist: cryptography
|
|
|
33
53
|
为了方便修改,将原项目中的文件复制到本项目中,然后进行修改
|
|
34
54
|
|
|
35
55
|
|
|
56
|
+
# 可优化点
|
|
57
|
+
|
|
58
|
+
1. 前端优化。目前项目架构是`前后端不分离架构`,前端使用原始的html三件套。可以优化为前后端分离架构,基于Vue等开发框架,复用组件库,优化界面。
|
|
59
|
+
|
|
60
|
+
2. 后端优化。支持提供调用jmcomic功能的后端接口。
|
|
36
61
|
|
|
37
|
-
# 使用方式
|
|
38
62
|
|
|
63
|
+
# 使用方式
|
|
39
64
|
|
|
40
65
|
|
|
41
66
|
## 1. pip安装
|
|
@@ -113,12 +138,28 @@ op.wait_all_plugins_finish()
|
|
|
113
138
|
# 效果图(文件浏览、整章看图)
|
|
114
139
|
|
|
115
140
|
## 1. 电脑浏览器访问
|
|
141
|
+
|
|
142
|
+
### 登录页
|
|
116
143
|

|
|
144
|
+
|
|
145
|
+
### 文件夹列表页
|
|
117
146
|

|
|
147
|
+

|
|
148
|
+
|
|
149
|
+
### 看本模式
|
|
118
150
|

|
|
119
151
|
|
|
152
|
+
### 文件夹&看本 二合一模式
|
|
153
|
+

|
|
154
|
+
|
|
120
155
|
## 2. 手机浏览器访问
|
|
156
|
+
|
|
157
|
+
### 登录页
|
|
121
158
|

|
|
122
|
-
|
|
159
|
+
|
|
160
|
+
### 文件夹列表页
|
|
161
|
+

|
|
162
|
+
|
|
163
|
+
### 看本模式
|
|
123
164
|

|
|
124
165
|
|
|
@@ -1,5 +1,15 @@
|
|
|
1
1
|
# plugin-jm-server
|
|
2
2
|
|
|
3
|
+
“离线版”禁漫天堂
|
|
4
|
+
|
|
5
|
+
该项目会在本地起一个`文件服务器`,支持用浏览器查看文件夹内的图片,界面模仿禁漫的章节观看页面,并适配手机端。
|
|
6
|
+
|
|
7
|
+
用浏览器的好处就是支持很多浏览器插件和脚本,例如:
|
|
8
|
+
|
|
9
|
+
* 双页阅读插件:https://sleazyfork.org/zh-CN/scripts/374903-comicread
|
|
10
|
+
|
|
11
|
+
# 想法起源
|
|
12
|
+
|
|
3
13
|
想法起源:https://github.com/hect0x7/JMComic-Crawler-Python/issues/192
|
|
4
14
|
|
|
5
15
|
基于原项目:https://github.com/AiCorein/Flask-Files-Server
|
|
@@ -7,9 +17,14 @@
|
|
|
7
17
|
为了方便修改,将原项目中的文件复制到本项目中,然后进行修改
|
|
8
18
|
|
|
9
19
|
|
|
20
|
+
# 可优化点
|
|
21
|
+
|
|
22
|
+
1. 前端优化。目前项目架构是`前后端不分离架构`,前端使用原始的html三件套。可以优化为前后端分离架构,基于Vue等开发框架,复用组件库,优化界面。
|
|
23
|
+
|
|
24
|
+
2. 后端优化。支持提供调用jmcomic功能的后端接口。
|
|
10
25
|
|
|
11
|
-
# 使用方式
|
|
12
26
|
|
|
27
|
+
# 使用方式
|
|
13
28
|
|
|
14
29
|
|
|
15
30
|
## 1. pip安装
|
|
@@ -87,12 +102,28 @@ op.wait_all_plugins_finish()
|
|
|
87
102
|
# 效果图(文件浏览、整章看图)
|
|
88
103
|
|
|
89
104
|
## 1. 电脑浏览器访问
|
|
105
|
+
|
|
106
|
+
### 登录页
|
|
90
107
|

|
|
108
|
+
|
|
109
|
+
### 文件夹列表页
|
|
91
110
|

|
|
111
|
+

|
|
112
|
+
|
|
113
|
+
### 看本模式
|
|
92
114
|

|
|
93
115
|
|
|
116
|
+
### 文件夹&看本 二合一模式
|
|
117
|
+

|
|
118
|
+
|
|
94
119
|
## 2. 手机浏览器访问
|
|
120
|
+
|
|
121
|
+
### 登录页
|
|
95
122
|

|
|
96
|
-
|
|
123
|
+
|
|
124
|
+
### 文件夹列表页
|
|
125
|
+

|
|
126
|
+
|
|
127
|
+
### 看本模式
|
|
97
128
|

|
|
98
129
|
|
|
@@ -8,7 +8,7 @@ from typing import Optional
|
|
|
8
8
|
import common
|
|
9
9
|
from flask import Flask, abort, Response, stream_with_context
|
|
10
10
|
from flask import render_template, send_from_directory
|
|
11
|
-
from flask import request, session, redirect, flash
|
|
11
|
+
from flask import request, session, redirect, flash, jsonify
|
|
12
12
|
|
|
13
13
|
from .files import FileManager
|
|
14
14
|
|
|
@@ -22,10 +22,12 @@ class JmServer:
|
|
|
22
22
|
def __init__(self,
|
|
23
23
|
default_path,
|
|
24
24
|
password,
|
|
25
|
+
*,
|
|
25
26
|
jm_option=None,
|
|
26
27
|
ip_whitelist=None,
|
|
27
28
|
current_path=None,
|
|
28
29
|
img_overwrite: Optional[dict] = None,
|
|
30
|
+
env=None,
|
|
29
31
|
**extra,
|
|
30
32
|
):
|
|
31
33
|
"""
|
|
@@ -59,6 +61,9 @@ class JmServer:
|
|
|
59
61
|
import queue
|
|
60
62
|
self.jm_log_msg_queue = queue.Queue()
|
|
61
63
|
self.__hook_jm_logging()
|
|
64
|
+
if env:
|
|
65
|
+
for k, v in env.items():
|
|
66
|
+
os.environ[k] = v
|
|
62
67
|
|
|
63
68
|
def __hook_jm_logging(self):
|
|
64
69
|
import jmcomic
|
|
@@ -77,7 +82,7 @@ class JmServer:
|
|
|
77
82
|
"""
|
|
78
83
|
验证登录状态
|
|
79
84
|
"""
|
|
80
|
-
if session.get('password', None) == self.password:
|
|
85
|
+
if (self.password == '') or session.get('password', None) == self.password:
|
|
81
86
|
return True
|
|
82
87
|
else:
|
|
83
88
|
return False
|
|
@@ -112,9 +117,75 @@ class JmServer:
|
|
|
112
117
|
"""
|
|
113
118
|
url添加一个随机参数,防止浏览器缓存
|
|
114
119
|
"""
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
120
|
+
from random import randint
|
|
121
|
+
return randint(100000, 1000000)
|
|
122
|
+
|
|
123
|
+
def spa_view(self):
|
|
124
|
+
"""
|
|
125
|
+
[New] V2 SPA Interface (PC Only)
|
|
126
|
+
"""
|
|
127
|
+
if not self.verify():
|
|
128
|
+
return redirect('/login')
|
|
129
|
+
|
|
130
|
+
# 获取路径参数,如果为空则使用默认路径
|
|
131
|
+
path = request.args.get('path', None)
|
|
132
|
+
if path is None:
|
|
133
|
+
path = self.file_manager.default_path
|
|
134
|
+
|
|
135
|
+
path = os.path.abspath(path)
|
|
136
|
+
path = common.fix_filepath(path)
|
|
137
|
+
|
|
138
|
+
if common.file_not_exists(path):
|
|
139
|
+
return abort(404)
|
|
140
|
+
|
|
141
|
+
return render_template('index_spa.html',
|
|
142
|
+
data={
|
|
143
|
+
'currentPath': path,
|
|
144
|
+
'defaultPath': self.file_manager.default_path,
|
|
145
|
+
'drivers': self.file_manager.DRIVERS_LIST
|
|
146
|
+
},
|
|
147
|
+
randomArg=self.url_random_arg())
|
|
148
|
+
|
|
149
|
+
def api_list_files(self):
|
|
150
|
+
"""
|
|
151
|
+
[New] API: List files in directory
|
|
152
|
+
"""
|
|
153
|
+
if not self.verify():
|
|
154
|
+
return abort(403)
|
|
155
|
+
|
|
156
|
+
path = request.args.get('path', self.file_manager.default_path)
|
|
157
|
+
path = os.path.abspath(path)
|
|
158
|
+
path = common.fix_filepath(path)
|
|
159
|
+
|
|
160
|
+
if common.file_not_exists(path):
|
|
161
|
+
return jsonify({'error': 'Path not found'}), 404
|
|
162
|
+
|
|
163
|
+
files_data = self.file_manager.get_files_data(path)
|
|
164
|
+
return jsonify({
|
|
165
|
+
'currentPath': path,
|
|
166
|
+
'files': files_data
|
|
167
|
+
})
|
|
168
|
+
|
|
169
|
+
def api_album_images(self):
|
|
170
|
+
"""
|
|
171
|
+
[New] API: Get images for an album
|
|
172
|
+
"""
|
|
173
|
+
if not self.verify():
|
|
174
|
+
return abort(403)
|
|
175
|
+
|
|
176
|
+
path = request.args.get('path', None)
|
|
177
|
+
if not path:
|
|
178
|
+
return jsonify({'error': 'Path required'}), 400
|
|
179
|
+
|
|
180
|
+
path = os.path.abspath(path)
|
|
181
|
+
if common.file_not_exists(path):
|
|
182
|
+
return jsonify({'error': 'Path not found'}), 404
|
|
183
|
+
|
|
184
|
+
images = self.file_manager.get_jm_view_images(path)
|
|
185
|
+
return jsonify({
|
|
186
|
+
'title': common.of_file_name(path),
|
|
187
|
+
'images': images
|
|
188
|
+
})
|
|
118
189
|
|
|
119
190
|
def jm_view(self):
|
|
120
191
|
"""
|
|
@@ -189,6 +260,7 @@ class JmServer:
|
|
|
189
260
|
"files": self.file_manager.get_files_data(path),
|
|
190
261
|
"drivers": self.file_manager.DRIVERS_LIST,
|
|
191
262
|
"currentPath": path,
|
|
263
|
+
"defaultPath": self.file_manager.default_path
|
|
192
264
|
},
|
|
193
265
|
randomArg=self.url_random_arg())
|
|
194
266
|
|
|
@@ -314,8 +386,14 @@ class JmServer:
|
|
|
314
386
|
finally:
|
|
315
387
|
self.jm_log_msg_queue.put(end)
|
|
316
388
|
|
|
317
|
-
def
|
|
318
|
-
|
|
389
|
+
def open_directory(self, directory):
|
|
390
|
+
path = os.path.abspath(directory)
|
|
391
|
+
# os.startfile(path) # Windows特有,打开文件夹
|
|
392
|
+
import subprocess
|
|
393
|
+
subprocess.Popen(f'explorer /select,"{path}"')
|
|
394
|
+
return ''
|
|
395
|
+
|
|
396
|
+
def register_routes(self):
|
|
319
397
|
# 添加路由
|
|
320
398
|
self.app.add_url_rule('/jm_view', 'jm_view', self.jm_view, methods=['GET'])
|
|
321
399
|
self.app.add_url_rule("/view_file/", 'view_file', self.view_file, methods=['GET'], strict_slashes=False)
|
|
@@ -323,8 +401,18 @@ class JmServer:
|
|
|
323
401
|
self.app.add_url_rule('/login', 'login', self.login, methods=['GET', 'POST'])
|
|
324
402
|
self.app.add_url_rule('/logout', 'logout', self.logout, methods=['GET', 'POST'])
|
|
325
403
|
self.app.add_url_rule("/download_file/<filename>", 'file_content', self.file_content)
|
|
404
|
+
self.app.add_url_rule('/open/<path:directory>', 'open_directory', self.open_directory)
|
|
326
405
|
self.app.add_url_rule("/upload_file", 'upload', self.upload, methods=['GET', 'POST'])
|
|
327
406
|
self.app.add_url_rule("/stream", 'stream', self.stream, methods=['GET', 'POST'])
|
|
407
|
+
|
|
408
|
+
# [New] SPA Routes
|
|
409
|
+
self.app.add_url_rule("/spa", 'spa_view', self.spa_view, methods=['GET'])
|
|
410
|
+
self.app.add_url_rule("/api/list_files", 'api_list_files', self.api_list_files, methods=['GET'])
|
|
411
|
+
self.app.add_url_rule("/api/album_images", 'api_album_images', self.api_album_images, methods=['GET'])
|
|
412
|
+
|
|
413
|
+
def run(self, **kwargs):
|
|
414
|
+
kwargs.setdefault('port', self.DEFAULT_PORT)
|
|
415
|
+
self.register_routes()
|
|
328
416
|
# 监听在所有 IP 地址上
|
|
329
417
|
self.app.run(**kwargs)
|
|
330
418
|
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import os
|
|
2
|
+
import re
|
|
2
3
|
|
|
3
4
|
|
|
4
5
|
def get_winDriver():
|
|
@@ -23,11 +24,11 @@ def get_winDriver():
|
|
|
23
24
|
driver_list[i] = driver_name
|
|
24
25
|
i += 1
|
|
25
26
|
except PermissionError as e:
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
#
|
|
29
|
-
|
|
30
|
-
|
|
27
|
+
del driver_list[i]
|
|
28
|
+
mobj = re.match(r'\[WinError (\d+)\]', str(e))
|
|
29
|
+
# ERROR_NOT_READY, ERROR_ACCESS_DENIED
|
|
30
|
+
if mobj is not None and mobj.group(1) not in {'21', '5'}:
|
|
31
|
+
print(f'Drive {driver_name} unexpectedly unavailable: {e}')
|
|
31
32
|
finally:
|
|
32
33
|
num -= 1
|
|
33
34
|
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
from urllib.parse import quote
|
|
2
|
+
import os
|
|
3
|
+
import time
|
|
4
|
+
import re
|
|
5
|
+
|
|
6
|
+
import common
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class FileManager:
|
|
10
|
+
def __init__(self, default_path, current_path):
|
|
11
|
+
self.default_path = default_path
|
|
12
|
+
self.current_path = current_path
|
|
13
|
+
|
|
14
|
+
@property
|
|
15
|
+
def DRIVERS_LIST(self):
|
|
16
|
+
# 判断如果是windows系统
|
|
17
|
+
if os.name == 'nt':
|
|
18
|
+
from .driver import get_winDriver
|
|
19
|
+
return get_winDriver()
|
|
20
|
+
else:
|
|
21
|
+
return ['/']
|
|
22
|
+
|
|
23
|
+
def get_jm_view_images(self, path):
|
|
24
|
+
images_data = []
|
|
25
|
+
|
|
26
|
+
give_up_sort = False
|
|
27
|
+
|
|
28
|
+
for f in self.files_of_dir_safe(path):
|
|
29
|
+
if not self.is_image_file(f):
|
|
30
|
+
continue
|
|
31
|
+
f = quote(f)
|
|
32
|
+
name = common.of_file_name(f)
|
|
33
|
+
try:
|
|
34
|
+
index = int(name[:name.index('.')])
|
|
35
|
+
except ValueError:
|
|
36
|
+
give_up_sort = True
|
|
37
|
+
index = None
|
|
38
|
+
|
|
39
|
+
images_data.append({
|
|
40
|
+
'filename': name,
|
|
41
|
+
'data_original': f'/view_file?path={f}',
|
|
42
|
+
'index': index,
|
|
43
|
+
})
|
|
44
|
+
|
|
45
|
+
if give_up_sort is False:
|
|
46
|
+
images_data.sort(key=lambda item: item['index'])
|
|
47
|
+
|
|
48
|
+
return images_data
|
|
49
|
+
|
|
50
|
+
@staticmethod
|
|
51
|
+
def is_image_file(filename):
|
|
52
|
+
file_extension = filename.lower().split('.')[-1]
|
|
53
|
+
image_extensions = ['jpg', 'jpeg', 'png', 'gif', 'bmp', 'tiff', 'webp']
|
|
54
|
+
return file_extension in image_extensions
|
|
55
|
+
|
|
56
|
+
@staticmethod
|
|
57
|
+
def files_of_dir_safe(dir_path):
|
|
58
|
+
try:
|
|
59
|
+
return common.files_of_dir(dir_path)
|
|
60
|
+
except OSError:
|
|
61
|
+
return []
|
|
62
|
+
|
|
63
|
+
def check_dir_can_open_jm_view(self, dirpath):
|
|
64
|
+
return any(f for f in self.files_of_dir_safe(dirpath) if self.is_image_file(f))
|
|
65
|
+
|
|
66
|
+
def build_one_path_info(self, file_path, dtype=''):
|
|
67
|
+
jm_view, the_type = self.get_file_type(file_path)
|
|
68
|
+
|
|
69
|
+
name = common.of_file_name(file_path)
|
|
70
|
+
|
|
71
|
+
try:
|
|
72
|
+
size = os.path.getsize(file_path)
|
|
73
|
+
except OSError:
|
|
74
|
+
return
|
|
75
|
+
|
|
76
|
+
size = dtype if dtype != '' else self.file_size_format(size, the_type)
|
|
77
|
+
|
|
78
|
+
try:
|
|
79
|
+
getctime = os.path.getctime(file_path)
|
|
80
|
+
ctime = time.localtime(getctime)
|
|
81
|
+
time_str = time.strftime("%Y-%m-%d %H:%M:%S", ctime)
|
|
82
|
+
except OSError:
|
|
83
|
+
return
|
|
84
|
+
|
|
85
|
+
first_img_url = ''
|
|
86
|
+
if jm_view and the_type == 'dir':
|
|
87
|
+
imgs = self.get_jm_view_images(file_path)
|
|
88
|
+
if imgs:
|
|
89
|
+
first_img_url = imgs[0]
|
|
90
|
+
|
|
91
|
+
if name.endswith('.lnk'):
|
|
92
|
+
target_path = self.get_target_path(file_path)
|
|
93
|
+
return self.build_one_path_info(target_path, 'Link')
|
|
94
|
+
|
|
95
|
+
return {
|
|
96
|
+
"name": name,
|
|
97
|
+
'path': file_path,
|
|
98
|
+
'href': f'/?path={file_path}' if the_type == 'dir' else f'./download_file/{name}',
|
|
99
|
+
"size": size,
|
|
100
|
+
"ctime": time_str,
|
|
101
|
+
"type": the_type,
|
|
102
|
+
'jm_view': jm_view,
|
|
103
|
+
'first_img_url': first_img_url
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
def get_files_data(self, path):
|
|
107
|
+
files = list(filter(bool, map(self.build_one_path_info, self.files_of_dir_safe(path))))
|
|
108
|
+
self.current_path = path
|
|
109
|
+
files = self.sort_files(files)
|
|
110
|
+
return files
|
|
111
|
+
|
|
112
|
+
def sort_files(self, files: list):
|
|
113
|
+
def natural_key(item):
|
|
114
|
+
return [int(text) if text.isdigit() else text.lower()
|
|
115
|
+
for text in re.split(r'(\d+)', item['name'])]
|
|
116
|
+
|
|
117
|
+
# Split into groups
|
|
118
|
+
jm_albums = []
|
|
119
|
+
other_dirs = []
|
|
120
|
+
other_files = []
|
|
121
|
+
|
|
122
|
+
for f in files:
|
|
123
|
+
if f['jm_view']:
|
|
124
|
+
jm_albums.append(f)
|
|
125
|
+
elif f['type'] == 'dir':
|
|
126
|
+
other_dirs.append(f)
|
|
127
|
+
else:
|
|
128
|
+
other_files.append(f)
|
|
129
|
+
|
|
130
|
+
# Sort each group
|
|
131
|
+
jm_albums.sort(key=natural_key)
|
|
132
|
+
other_dirs.sort(key=natural_key)
|
|
133
|
+
other_files.sort(key=natural_key)
|
|
134
|
+
|
|
135
|
+
return jm_albums + other_dirs + other_files
|
|
136
|
+
|
|
137
|
+
def get_file_type(self, file_path):
|
|
138
|
+
if os.path.isfile(file_path):
|
|
139
|
+
the_type = 'file'
|
|
140
|
+
jm_view = self.check_dir_can_open_jm_view(common.of_dir_path(file_path))
|
|
141
|
+
else:
|
|
142
|
+
the_type = 'dir'
|
|
143
|
+
jm_view = self.check_dir_can_open_jm_view(file_path)
|
|
144
|
+
return jm_view, the_type
|
|
145
|
+
|
|
146
|
+
@staticmethod
|
|
147
|
+
def get_target_path(lnk_path: str) -> str:
|
|
148
|
+
try:
|
|
149
|
+
import pylnk3
|
|
150
|
+
lnk = pylnk3.parse(lnk_path)
|
|
151
|
+
return lnk.path.replace("\\", '/').replace("//", '/') # 获取目标文件/文件夹路径
|
|
152
|
+
except Exception as e:
|
|
153
|
+
return lnk_path
|
|
154
|
+
|
|
155
|
+
@staticmethod
|
|
156
|
+
def file_size_format(size, the_type):
|
|
157
|
+
if the_type == 'dir':
|
|
158
|
+
return '<DIR>'
|
|
159
|
+
else:
|
|
160
|
+
if size < 1024:
|
|
161
|
+
return '%i' % size + ' B'
|
|
162
|
+
elif 1024 < size <= 1048576:
|
|
163
|
+
return '%.1f' % float(size / 1024) + ' KB'
|
|
164
|
+
elif 1048576 < size <= 1073741824:
|
|
165
|
+
return '%.1f' % float(size / 1048576) + ' MB'
|
|
166
|
+
elif 1073741824 < size <= 1099511627776:
|
|
167
|
+
return '%.1f' % float(size / 1073741824) + ' GB'
|
|
168
|
+
|
|
169
|
+
def get_current_path(self):
|
|
170
|
+
return self.current_path
|