Skip to content

Commit e3794cc

Browse files
committed
add:全随机/random目录
1 parent 56dd08c commit e3794cc

2 files changed

Lines changed: 103 additions & 23 deletions

File tree

app/routes/images.py

Lines changed: 50 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
import logging
66
from flask import Blueprint, redirect, send_from_directory, abort, request, render_template
77
from ..utils.security import get_safe_path, is_banned
8-
from ..utils.cache import get_random_image, invalidate_cache
8+
from ..utils.cache import get_random_image, get_random_image_from_all_folders, invalidate_cache
99
from ..config.config import Config
1010

1111
# 配置日志
@@ -14,10 +14,57 @@
1414
# 创建蓝图
1515
images_bp = Blueprint('images', __name__)
1616

17+
@images_bp.route('/random')
18+
def serve_random_from_all():
19+
"""
20+
从所有文件夹中随机选择并返回图片
21+
"""
22+
# 检查封禁状态
23+
client_ip = request.remote_addr
24+
current_path = request.path
25+
banned, remaining, end_time = is_banned(client_ip, current_path, Config.BAN_DURATION)
26+
27+
if banned:
28+
return render_template('too_many_requests.html',
29+
retry_after=int(remaining),
30+
end_time=int(end_time),
31+
client_ip=client_ip,
32+
target_url=current_path), 429
33+
34+
max_attempts = 3 # 最大重试次数
35+
attempt = 0
36+
37+
while attempt < max_attempts:
38+
# 从所有文件夹中随机选择图片
39+
folder, image = get_random_image_from_all_folders(Config.IMAGE_BASE, Config.IMAGE_EXTENSIONS)
40+
41+
if not folder or not image:
42+
abort(404) # 无有效图像
43+
44+
# 检查图像文件是否存在
45+
folder_path = get_safe_path(Config.IMAGE_BASE, folder)
46+
image_path = get_safe_path(folder_path, image)
47+
48+
if image_path and os.path.isfile(image_path):
49+
# 重定向到实际图像URL
50+
return redirect(f'/{folder}/{image}')
51+
52+
# 文件不存在:记录日志并尝试重建缓存
53+
logger.warning(f"图像文件不存在: {image_path}, 尝试 {attempt + 1}/{max_attempts}")
54+
attempt += 1
55+
56+
# 使缓存失效
57+
invalidate_cache(folder)
58+
59+
# 多次尝试后仍失败
60+
logger.error("无法从所有文件夹中找到有效图像")
61+
abort(404)
62+
63+
1764
@images_bp.route('/<path:folder>')
1865
def serve_sequential_image(folder):
1966
"""
20-
顺序服务图像:按预定义的随机顺序循环显示文件夹中的图像
67+
随机服务图像:从指定文件夹中随机返回图像
2168
"""
2269
# 首先检查封禁状态
2370
client_ip = request.remote_addr
@@ -46,7 +93,7 @@ def serve_sequential_image(folder):
4693
attempt = 0
4794

4895
while attempt < max_attempts:
49-
# 获取随机图像
96+
# 获取随机图像(真随机)
5097
image = get_random_image(Config.IMAGE_BASE, folder, Config.IMAGE_EXTENSIONS)
5198
if not image:
5299
abort(404) # 无有效图像

app/utils/cache.py

Lines changed: 53 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ def init_folder_cache(image_base, folder, image_extensions):
4949

5050
def get_random_image(image_base, folder, image_extensions):
5151
"""
52-
获取文件夹中的随机图像
52+
获取文件夹中的随机图像(真随机)
5353
5454
Args:
5555
image_base: 图像基础目录
@@ -60,37 +60,70 @@ def get_random_image(image_base, folder, image_extensions):
6060
随机图像文件名或None
6161
"""
6262
with cache_lock: # 线程安全操作
63-
# 如果缓存中没有该文件夹
63+
# 如果缓存中没有该文件夹,初始化缓存
6464
if folder not in folder_cache:
65-
images = init_folder_cache(image_base, folder, image_extensions) # 初始化缓存
65+
images = init_folder_cache(image_base, folder, image_extensions)
6666
if not images:
6767
return None # 无有效图像
68-
69-
# 创建基于文件夹和时间的随机种子
70-
seed = hash(f"{folder}-{time.time()}") % (2 ** 32)
71-
random.seed(seed)
72-
shuffled = images.copy()
73-
random.shuffle(shuffled) # 随机打乱图像列表
74-
75-
# 将打乱后的列表存入缓存
68+
# 存储图像列表到缓存
7669
folder_cache[folder] = {
77-
'images': shuffled,
78-
'index': 0, # 当前索引位置
79-
'seed': seed # 使用的随机种子
70+
'images': images
8071
}
8172

8273
cache = folder_cache[folder]
8374
if not cache['images']:
8475
del folder_cache[folder] # 空列表则删除缓存项
8576
return None
8677

87-
# 获取当前图像并更新索引
88-
current_index = cache['index']
89-
image = cache['images'][current_index]
90-
# 循环索引(到达末尾后回到开头)
91-
cache['index'] = (current_index + 1) % len(cache['images'])
78+
# 真随机:每次都随机选择一个图像
79+
return random.choice(cache['images'])
80+
81+
82+
def get_random_image_from_all_folders(image_base, image_extensions):
83+
"""
84+
从所有文件夹中随机选择一张图片
85+
86+
Args:
87+
image_base: 图像基础目录
88+
image_extensions: 支持的图像扩展名列表
89+
90+
Returns:
91+
(文件夹名称, 图像文件名) 或 (None, None)
92+
"""
93+
with cache_lock:
94+
# 获取所有子文件夹
95+
try:
96+
subfolders = [d for d in os.listdir(image_base)
97+
if os.path.isdir(get_safe_path(image_base, d))]
98+
except Exception as e:
99+
logger.error(f"获取子文件夹列表失败: {str(e)}")
100+
return None, None
101+
102+
if not subfolders:
103+
logger.warning("没有找到任何子文件夹")
104+
return None, None
105+
106+
# 收集所有文件夹中的所有图片
107+
all_images = [] # 格式: [(folder, image), ...]
108+
109+
for folder in subfolders:
110+
# 如果缓存中没有该文件夹,初始化缓存
111+
if folder not in folder_cache:
112+
images = init_folder_cache(image_base, folder, image_extensions)
113+
if images:
114+
folder_cache[folder] = {'images': images}
115+
116+
# 从缓存中获取图片列表
117+
if folder in folder_cache and folder_cache[folder]['images']:
118+
for image in folder_cache[folder]['images']:
119+
all_images.append((folder, image))
120+
121+
if not all_images:
122+
logger.warning("没有找到任何图片")
123+
return None, None
92124

93-
return image
125+
# 真随机:随机选择一张图片
126+
return random.choice(all_images)
94127

95128

96129
def invalidate_cache(folder):

0 commit comments

Comments
 (0)