nonebot-plugin-randpic 2.0.1__tar.gz → 2.0.2__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.
- {nonebot_plugin_randpic-2.0.1 → nonebot_plugin_randpic-2.0.2}/PKG-INFO +3 -3
- {nonebot_plugin_randpic-2.0.1 → nonebot_plugin_randpic-2.0.2}/README.md +2 -2
- {nonebot_plugin_randpic-2.0.1 → nonebot_plugin_randpic-2.0.2}/nonebot_plugin_randpic/ali_oss.py +1 -1
- {nonebot_plugin_randpic-2.0.1 → nonebot_plugin_randpic-2.0.2}/nonebot_plugin_randpic/service.py +2 -3
- {nonebot_plugin_randpic-2.0.1 → nonebot_plugin_randpic-2.0.2}/nonebot_plugin_randpic/web.py +7 -18
- {nonebot_plugin_randpic-2.0.1 → nonebot_plugin_randpic-2.0.2}/pyproject.toml +1 -1
- {nonebot_plugin_randpic-2.0.1 → nonebot_plugin_randpic-2.0.2}/LICENSE +0 -0
- {nonebot_plugin_randpic-2.0.1 → nonebot_plugin_randpic-2.0.2}/nonebot_plugin_randpic/__init__.py +0 -0
- {nonebot_plugin_randpic-2.0.1 → nonebot_plugin_randpic-2.0.2}/nonebot_plugin_randpic/compress.py +0 -0
- {nonebot_plugin_randpic-2.0.1 → nonebot_plugin_randpic-2.0.2}/nonebot_plugin_randpic/config.py +0 -0
- {nonebot_plugin_randpic-2.0.1 → nonebot_plugin_randpic-2.0.2}/nonebot_plugin_randpic/drivers/fastapi.py +0 -0
- {nonebot_plugin_randpic-2.0.1 → nonebot_plugin_randpic-2.0.2}/nonebot_plugin_randpic/handlers.py +0 -0
- {nonebot_plugin_randpic-2.0.1 → nonebot_plugin_randpic-2.0.2}/nonebot_plugin_randpic/journal.py +0 -0
- {nonebot_plugin_randpic-2.0.1 → nonebot_plugin_randpic-2.0.2}/nonebot_plugin_randpic/library.py +0 -0
- {nonebot_plugin_randpic-2.0.1 → nonebot_plugin_randpic-2.0.2}/nonebot_plugin_randpic/models.py +0 -0
- {nonebot_plugin_randpic-2.0.1 → nonebot_plugin_randpic-2.0.2}/nonebot_plugin_randpic/progress.py +0 -0
- {nonebot_plugin_randpic-2.0.1 → nonebot_plugin_randpic-2.0.2}/nonebot_plugin_randpic/repository.py +0 -0
- {nonebot_plugin_randpic-2.0.1 → nonebot_plugin_randpic-2.0.2}/nonebot_plugin_randpic/utils.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: nonebot-plugin-randpic
|
|
3
|
-
Version: 2.0.
|
|
3
|
+
Version: 2.0.2
|
|
4
4
|
Summary: 一个通过指令随机发送你存储的图片的nonebot2插件
|
|
5
5
|
License: MIT
|
|
6
6
|
License-File: LICENSE
|
|
@@ -105,7 +105,7 @@ Bot 运行期间请通过指令增删图片,直接修改文件需重启才能
|
|
|
105
105
|
|
|
106
106
|
使用 FastAPI 驱动时,Bot 启动后即可通过 `http://<host>:<port>/randpic/` 查看图库,无需配置 OSS。默认每页 100 张图片,可通过 `randpic_web_page_size` 调整。图片使用 `loading="lazy"`,按需加载。
|
|
107
107
|
|
|
108
|
-
|
|
108
|
+
增删图片后本地页面立即重新发布,浏览器手动刷新即可查看最新内容。没有 FastAPI 服务的驱动仍可使用聊天指令和 OSS 同步。
|
|
109
109
|
|
|
110
110
|
#### 阿里云 OSS
|
|
111
111
|
|
|
@@ -122,7 +122,7 @@ Bot 运行期间请通过指令增删图片,直接修改文件需重启才能
|
|
|
122
122
|
|
|
123
123
|
启动、添加和删除后会自动同步;`上传oss` 可手动全量重新发布、重试未完成任务。默认最多 16 个并发请求,普通终端中以单行动态进度显示完成数、百分比和成功/失败数,最多每秒刷新 5 次;其他插件的默认 NoneBot 日志显示在进度行上方。同步结束后清除动态行,只保留一条结果汇总,错误详情仍单独记录。输出重定向、非交互控制台或已移除 NoneBot 默认日志处理器时仅输出汇总。
|
|
124
124
|
|
|
125
|
-
失败任务存入数据库,后台约每 30 秒重试,重启后继续处理。OSS
|
|
125
|
+
失败任务存入数据库,后台约每 30 秒重试,重启后继续处理。OSS 的图片和页面依次同步,网络故障期间云端可能暂时落后于本地图。`randpic_oss_no_upload_list` 只影响 OSS,本地网页仍显示所有配置的分类;此前已同步的分类被排除后,其受本插件跟踪的云端对象会清理。未被数据库跟踪的历史对象不保证自动清理。
|
|
126
126
|
|
|
127
127
|
## 💿 安装
|
|
128
128
|
|
|
@@ -74,7 +74,7 @@ Bot 运行期间请通过指令增删图片,直接修改文件需重启才能
|
|
|
74
74
|
|
|
75
75
|
使用 FastAPI 驱动时,Bot 启动后即可通过 `http://<host>:<port>/randpic/` 查看图库,无需配置 OSS。默认每页 100 张图片,可通过 `randpic_web_page_size` 调整。图片使用 `loading="lazy"`,按需加载。
|
|
76
76
|
|
|
77
|
-
|
|
77
|
+
增删图片后本地页面立即重新发布,浏览器手动刷新即可查看最新内容。没有 FastAPI 服务的驱动仍可使用聊天指令和 OSS 同步。
|
|
78
78
|
|
|
79
79
|
#### 阿里云 OSS
|
|
80
80
|
|
|
@@ -91,7 +91,7 @@ Bot 运行期间请通过指令增删图片,直接修改文件需重启才能
|
|
|
91
91
|
|
|
92
92
|
启动、添加和删除后会自动同步;`上传oss` 可手动全量重新发布、重试未完成任务。默认最多 16 个并发请求,普通终端中以单行动态进度显示完成数、百分比和成功/失败数,最多每秒刷新 5 次;其他插件的默认 NoneBot 日志显示在进度行上方。同步结束后清除动态行,只保留一条结果汇总,错误详情仍单独记录。输出重定向、非交互控制台或已移除 NoneBot 默认日志处理器时仅输出汇总。
|
|
93
93
|
|
|
94
|
-
失败任务存入数据库,后台约每 30 秒重试,重启后继续处理。OSS
|
|
94
|
+
失败任务存入数据库,后台约每 30 秒重试,重启后继续处理。OSS 的图片和页面依次同步,网络故障期间云端可能暂时落后于本地图。`randpic_oss_no_upload_list` 只影响 OSS,本地网页仍显示所有配置的分类;此前已同步的分类被排除后,其受本插件跟踪的云端对象会清理。未被数据库跟踪的历史对象不保证自动清理。
|
|
95
95
|
|
|
96
96
|
## 💿 安装
|
|
97
97
|
|
{nonebot_plugin_randpic-2.0.1 → nonebot_plugin_randpic-2.0.2}/nonebot_plugin_randpic/ali_oss.py
RENAMED
|
@@ -44,7 +44,7 @@ class OSSUploaderV2:
|
|
|
44
44
|
result = await asyncio.wait_for(self.client.put_object(oss.PutObjectRequest(
|
|
45
45
|
bucket=self.bucket, key=oss_key, body=data,
|
|
46
46
|
content_type=mimetypes.guess_type(oss_key)[0] or 'application/octet-stream',
|
|
47
|
-
cache_control='no-cache' if oss_key.endswith(
|
|
47
|
+
cache_control='no-cache' if oss_key.endswith('.html') else 'public, max-age=31536000, immutable',
|
|
48
48
|
)), timeout=60)
|
|
49
49
|
if 200 <= result.status_code < 300:
|
|
50
50
|
return True
|
{nonebot_plugin_randpic-2.0.1 → nonebot_plugin_randpic-2.0.2}/nonebot_plugin_randpic/service.py
RENAMED
|
@@ -226,10 +226,9 @@ class RandpicService:
|
|
|
226
226
|
|
|
227
227
|
await asyncio.gather(*(worker() for _ in range(min(self.config.randpic_upload_concurrency, len(items)))))
|
|
228
228
|
|
|
229
|
-
#
|
|
230
|
-
await phase([job for job in jobs if not job.key.endswith(
|
|
229
|
+
# 先同步图片,再同步页面。
|
|
230
|
+
await phase([job for job in jobs if not job.key.endswith('.html')])
|
|
231
231
|
await phase([job for job in jobs if job.key.endswith('.html')])
|
|
232
|
-
await phase([job for job in jobs if job.key.endswith('.json')])
|
|
233
232
|
pending = len(await run_blocking(self.repository.sync_jobs))
|
|
234
233
|
elapsed = asyncio.get_running_loop().time() - started
|
|
235
234
|
summary = (f'OSS 同步完成:成功 {succeeded},失败 {failed},待处理 {pending},'
|
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
"""
|
|
1
|
+
"""静态网页发布:原子替换文件、分页与图片懒加载。"""
|
|
2
2
|
|
|
3
3
|
import hashlib
|
|
4
|
-
import json
|
|
5
4
|
import math
|
|
6
5
|
from html import escape
|
|
7
6
|
from pathlib import Path
|
|
@@ -67,8 +66,7 @@ def _url(image: ImageRecord) -> str:
|
|
|
67
66
|
return quote(image.filename, safe='') + '?v=' + image.content_hash[:16]
|
|
68
67
|
|
|
69
68
|
|
|
70
|
-
def _shell(title: str, home: str,
|
|
71
|
-
state = json.dumps({'version': version, 'command': command, 'page': page}, ensure_ascii=False).replace('<', '\\u003c')
|
|
69
|
+
def _shell(title: str, home: str, content: str) -> str:
|
|
72
70
|
return f'''<!doctype html><html lang="zh-CN"><head><meta charset="utf-8">
|
|
73
71
|
<meta name="viewport" content="width=device-width,initial-scale=1"><meta name="theme-color" content="#f5f6f2">
|
|
74
72
|
<title>{escape(title)} · Randpic</title><style>{GALLERY_STYLE}
|
|
@@ -77,22 +75,13 @@ def _shell(title: str, home: str, version: str, command: str, page: int, content
|
|
|
77
75
|
</style></head><body><div class="shell">
|
|
78
76
|
<nav class="topbar"><a class="brand" href="{home}"><span class="brand-mark">✳</span><span>RANDPIC / 图片收藏馆</span></a><span class="top-note">捕捉喜欢的瞬间</span></nav>
|
|
79
77
|
{content}<footer>Randpic · 收藏每一个喜欢的瞬间</footer></div>
|
|
80
|
-
|
|
81
|
-
setInterval(async()=>{{if(document.hidden)return;try{{
|
|
82
|
-
const response=await fetch(home+'catalog.json',{{cache:'no-store'}});if(!response.ok)return;
|
|
83
|
-
const next=await response.json();if(next.version===state.version)return;
|
|
84
|
-
if(state.command && (!(state.command in next.pages)||state.page>next.pages[state.command])){{location.href=state.command in next.pages?'./':home;return;}}
|
|
85
|
-
location.reload();}}catch(error){{}}}},15000);}})();</script></body></html>'''
|
|
78
|
+
</body></html>'''
|
|
86
79
|
|
|
87
80
|
|
|
88
81
|
def render_catalog(groups: Mapping[str, Sequence[ImageRecord]], page_size: int) -> Dict[str, bytes]:
|
|
89
|
-
"""
|
|
90
|
-
identity = [(command, [(image.id, image.filename, image.content_hash) for image in images])
|
|
91
|
-
for command, images in sorted(groups.items())]
|
|
92
|
-
version = hashlib.sha256(json.dumps(identity, ensure_ascii=False).encode()).hexdigest()
|
|
82
|
+
"""生成纯静态 HTML,只让内容实际变化的页面产生同步任务。"""
|
|
93
83
|
pages = {command: max(1, math.ceil(len(images) / page_size)) for command, images in groups.items()}
|
|
94
|
-
|
|
95
|
-
files = {'catalog.json': catalog}
|
|
84
|
+
files: Dict[str, bytes] = {}
|
|
96
85
|
total = sum(len(images) for images in groups.values())
|
|
97
86
|
cards = []
|
|
98
87
|
for command, images in sorted(groups.items()):
|
|
@@ -106,7 +95,7 @@ def render_catalog(groups: Mapping[str, Sequence[ImageRecord]], page_size: int)
|
|
|
106
95
|
home = f'''<header class="hero"><p class="eyebrow">YOUR IMAGE LIBRARY</p><h1>每一张,都值得<br>被好好收藏。</h1>
|
|
107
96
|
<p class="hero-copy">在这里慢慢翻看收藏的每一份灵感。</p></header><div class="section-head"><h2>全部分类</h2>
|
|
108
97
|
<span class="count">{len(groups)} 个分类 · {total} 张图片</span></div><main class="folder-grid">{''.join(cards)}</main>'''
|
|
109
|
-
files['index.html'] = _shell('图片收藏馆', './',
|
|
98
|
+
files['index.html'] = _shell('图片收藏馆', './', home).encode()
|
|
110
99
|
for command, images in groups.items():
|
|
111
100
|
for page in range(1, pages[command] + 1):
|
|
112
101
|
cards = []
|
|
@@ -128,7 +117,7 @@ def render_catalog(groups: Mapping[str, Sequence[ImageRecord]], page_size: int)
|
|
|
128
117
|
<header class="gallery-title"><p class="eyebrow">COLLECTION</p><h1>{escape(command)}</h1><p class="hero-copy">本分类共收藏 {len(images)} 张图片。</p></header>
|
|
129
118
|
<main class="image-grid">{''.join(cards)}</main><nav class="pagination">{''.join(navigation)}</nav>'''
|
|
130
119
|
filename = 'index.html' if page == 1 else f'page-{page}.html'
|
|
131
|
-
files[f'{command}/{filename}'] = _shell(command, '../',
|
|
120
|
+
files[f'{command}/{filename}'] = _shell(command, '../', content).encode()
|
|
132
121
|
return files
|
|
133
122
|
|
|
134
123
|
|
|
File without changes
|
{nonebot_plugin_randpic-2.0.1 → nonebot_plugin_randpic-2.0.2}/nonebot_plugin_randpic/__init__.py
RENAMED
|
File without changes
|
{nonebot_plugin_randpic-2.0.1 → nonebot_plugin_randpic-2.0.2}/nonebot_plugin_randpic/compress.py
RENAMED
|
File without changes
|
{nonebot_plugin_randpic-2.0.1 → nonebot_plugin_randpic-2.0.2}/nonebot_plugin_randpic/config.py
RENAMED
|
File without changes
|
|
File without changes
|
{nonebot_plugin_randpic-2.0.1 → nonebot_plugin_randpic-2.0.2}/nonebot_plugin_randpic/handlers.py
RENAMED
|
File without changes
|
{nonebot_plugin_randpic-2.0.1 → nonebot_plugin_randpic-2.0.2}/nonebot_plugin_randpic/journal.py
RENAMED
|
File without changes
|
{nonebot_plugin_randpic-2.0.1 → nonebot_plugin_randpic-2.0.2}/nonebot_plugin_randpic/library.py
RENAMED
|
File without changes
|
{nonebot_plugin_randpic-2.0.1 → nonebot_plugin_randpic-2.0.2}/nonebot_plugin_randpic/models.py
RENAMED
|
File without changes
|
{nonebot_plugin_randpic-2.0.1 → nonebot_plugin_randpic-2.0.2}/nonebot_plugin_randpic/progress.py
RENAMED
|
File without changes
|
{nonebot_plugin_randpic-2.0.1 → nonebot_plugin_randpic-2.0.2}/nonebot_plugin_randpic/repository.py
RENAMED
|
File without changes
|
{nonebot_plugin_randpic-2.0.1 → nonebot_plugin_randpic-2.0.2}/nonebot_plugin_randpic/utils.py
RENAMED
|
File without changes
|