update
This commit is contained in:
221
dict/tags.json
221
dict/tags.json
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"version": 2,
|
||||
"description": "标签词典 v2 — 9 大分类 + 人物规则 + 停用词",
|
||||
"version": 3,
|
||||
"description": "标签词典 v3 — 合并扩充 + 高频人名 include",
|
||||
"tags": {
|
||||
"style": {
|
||||
"label": "风格",
|
||||
@@ -42,7 +42,10 @@
|
||||
"sweet",
|
||||
"wild",
|
||||
"pure",
|
||||
"fashion"
|
||||
"fashion",
|
||||
"微博运动达人",
|
||||
"运动内衣",
|
||||
"运动服饰"
|
||||
]
|
||||
},
|
||||
"outfit": {
|
||||
@@ -50,7 +53,10 @@
|
||||
"color_bg": "#fdf2f8",
|
||||
"color_fg": "#db2777",
|
||||
"words": [
|
||||
"黑色礼服",
|
||||
"女秘书",
|
||||
"比基尼",
|
||||
"兔女郎",
|
||||
"泳装",
|
||||
"泳衣",
|
||||
"旗袍",
|
||||
@@ -102,7 +108,33 @@
|
||||
"shirt",
|
||||
"sweater",
|
||||
"coat",
|
||||
"heels"
|
||||
"heels",
|
||||
"OL",
|
||||
"吊带短裙",
|
||||
"吊带长裙",
|
||||
"和服",
|
||||
"女仆装",
|
||||
"学生装",
|
||||
"护士服",
|
||||
"抹胸服饰",
|
||||
"抹胸礼裙",
|
||||
"水手服",
|
||||
"白色吊带上衣",
|
||||
"白衬衫职场",
|
||||
"空姐制服",
|
||||
"蕾丝内衣",
|
||||
"蕾丝吊袜",
|
||||
"蕾丝吊裙",
|
||||
"蕾丝睡衣",
|
||||
"镂空内衣",
|
||||
"镂空服饰",
|
||||
"露肩上衣",
|
||||
"露肩服饰",
|
||||
"露肩短裙",
|
||||
"露肩礼裙",
|
||||
"露肩连衣短裙",
|
||||
"露肩连衣裙",
|
||||
"露肩长裙"
|
||||
]
|
||||
},
|
||||
"scene": {
|
||||
@@ -110,6 +142,7 @@
|
||||
"color_bg": "#f0fdf4",
|
||||
"color_fg": "#15803d",
|
||||
"words": [
|
||||
"办公室",
|
||||
"室内",
|
||||
"户外",
|
||||
"街拍",
|
||||
@@ -153,7 +186,9 @@
|
||||
"balcony",
|
||||
"car",
|
||||
"cafe",
|
||||
"hotel"
|
||||
"hotel",
|
||||
"室外泳池",
|
||||
"浴室场景写真"
|
||||
]
|
||||
},
|
||||
"body": {
|
||||
@@ -183,7 +218,17 @@
|
||||
"shoulders",
|
||||
"waist",
|
||||
"skin",
|
||||
"tattoo"
|
||||
"tattoo",
|
||||
"丝袜美腿写真",
|
||||
"丝袜美腿职场",
|
||||
"丝足美腿",
|
||||
"修长美腿",
|
||||
"小蛮腰",
|
||||
"美腿宝贝",
|
||||
"美腿系列写真",
|
||||
"黑丝美腿",
|
||||
"黑丝美腿写真",
|
||||
"黑丝美腿职场"
|
||||
]
|
||||
},
|
||||
"mood": {
|
||||
@@ -218,7 +263,9 @@
|
||||
"gentle",
|
||||
"wild",
|
||||
"lazy",
|
||||
"sweet"
|
||||
"sweet",
|
||||
"模特程开心",
|
||||
"魅惑黑丝"
|
||||
]
|
||||
},
|
||||
"topic": {
|
||||
@@ -226,6 +273,8 @@
|
||||
"color_bg": "#f0f9ff",
|
||||
"color_fg": "#0369a1",
|
||||
"words": [
|
||||
"Genshin",
|
||||
"姐妹花",
|
||||
"写真",
|
||||
"私房",
|
||||
"街拍",
|
||||
@@ -241,7 +290,21 @@
|
||||
"portrait",
|
||||
"selfie",
|
||||
"travel",
|
||||
"wedding"
|
||||
"wedding",
|
||||
"制服",
|
||||
"制服性感写真",
|
||||
"制服系列写真",
|
||||
"制服诱惑写真",
|
||||
"女警制服",
|
||||
"女警官制服",
|
||||
"学生制服",
|
||||
"情趣制服",
|
||||
"护士制服",
|
||||
"海军制服",
|
||||
"白色制服",
|
||||
"空乘制服",
|
||||
"职场制服",
|
||||
"警花制服"
|
||||
]
|
||||
},
|
||||
"position": {
|
||||
@@ -283,6 +346,7 @@
|
||||
"color_bg": "#f0fdfa",
|
||||
"color_fg": "#0f766e",
|
||||
"words": [
|
||||
"苏梅岛",
|
||||
"日本",
|
||||
"韩国",
|
||||
"中国",
|
||||
@@ -379,7 +443,79 @@
|
||||
"花漾",
|
||||
"BoLoli",
|
||||
"波萝社",
|
||||
"MyGirl"
|
||||
"MyGirl",
|
||||
"RUISG",
|
||||
"瑞丝馆",
|
||||
"Pure Media",
|
||||
"PureMedia",
|
||||
"XiuRen秀人网",
|
||||
"秀人",
|
||||
"IMiss爱蜜社",
|
||||
"尤蜜",
|
||||
"YouMi尤蜜",
|
||||
"YOUMI尤蜜荟",
|
||||
"XIAOYU语画界",
|
||||
"MFStar模范学院",
|
||||
"MFStar",
|
||||
"MFStar模特",
|
||||
"TGOD推女神",
|
||||
"DKGirl御女郎",
|
||||
"XINGYAN星颜社",
|
||||
"XINGYAN",
|
||||
"FEILIN嗲囡囡",
|
||||
"FEILIN",
|
||||
"Feiling",
|
||||
"飞灵",
|
||||
"CANDY糖果画报",
|
||||
"CANDY",
|
||||
"YouWu尤物馆",
|
||||
"YouWu",
|
||||
"尤物馆",
|
||||
"UXING优星馆",
|
||||
"UXING",
|
||||
"RuiSG瑞丝馆",
|
||||
"SIW斯文传媒",
|
||||
"SIW",
|
||||
"SLADY猎女神",
|
||||
"SLADY",
|
||||
"SSA丝社",
|
||||
"SSA",
|
||||
"SJA佳爷",
|
||||
"SJA",
|
||||
"TASHA系列",
|
||||
"TASHA",
|
||||
"Ugirls爱尤物",
|
||||
"Ugirls",
|
||||
"爱尤物",
|
||||
"V Girls",
|
||||
"VGIRL",
|
||||
"VGIRLS",
|
||||
"WingS影私荟",
|
||||
"WING",
|
||||
"YALAYI雅拉伊",
|
||||
"YALAYI",
|
||||
"ISHOW爱秀",
|
||||
"ISHOW",
|
||||
"BlueCake",
|
||||
"MiiTao蜜桃社",
|
||||
"MiiTao",
|
||||
"蜜桃社",
|
||||
"108TV",
|
||||
"108酱",
|
||||
"撸图",
|
||||
"情欲萝莉",
|
||||
"头条女神",
|
||||
"尤果网",
|
||||
"尤果圈",
|
||||
"虎牙",
|
||||
"星颜社",
|
||||
"绯月樱",
|
||||
"青豆客",
|
||||
"Beautyleg",
|
||||
"MFModel",
|
||||
"LeiLei",
|
||||
"Tristana",
|
||||
"Victoria Secret"
|
||||
]
|
||||
}
|
||||
},
|
||||
@@ -489,10 +625,67 @@
|
||||
"MFModel",
|
||||
"LeiLei",
|
||||
"Tristana",
|
||||
"Av"
|
||||
"Av",
|
||||
"写真",
|
||||
"情趣",
|
||||
"性感",
|
||||
"Impact",
|
||||
"宅男",
|
||||
"黑丝",
|
||||
"美腿",
|
||||
"真空",
|
||||
"诱惑",
|
||||
"私房",
|
||||
"气质",
|
||||
"女神",
|
||||
"丝袜",
|
||||
"黑色",
|
||||
"礼服",
|
||||
"Girl",
|
||||
"丝袜美腿",
|
||||
"诱惑写真",
|
||||
"分析师",
|
||||
"头条女神",
|
||||
"尤果网",
|
||||
"尤果圈",
|
||||
"波萝社",
|
||||
"BoLoli",
|
||||
"绯月樱",
|
||||
"青豆客",
|
||||
"Beautyleg",
|
||||
"108TV",
|
||||
"108酱",
|
||||
"撸图",
|
||||
"情欲萝莉",
|
||||
"星颜社",
|
||||
"爱尤物",
|
||||
"尤物馆"
|
||||
],
|
||||
"include": [
|
||||
"杨晨晨",
|
||||
"水淼",
|
||||
"王馨瑶",
|
||||
"轩美宣",
|
||||
"顾雪儿",
|
||||
"曼曼",
|
||||
"小乔",
|
||||
"佳佳",
|
||||
"安可",
|
||||
"舒淇",
|
||||
"林志玲",
|
||||
"刘亦菲",
|
||||
"蠢沫沫",
|
||||
"绯月樱",
|
||||
"鱼子酱",
|
||||
"陈小纭",
|
||||
"陆萱萱",
|
||||
"安然",
|
||||
"林星阑",
|
||||
"朱可儿",
|
||||
"张馨予",
|
||||
"程开心",
|
||||
"赵小米",
|
||||
"小齿优喵"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -26,6 +26,98 @@ impl Database {
|
||||
}).collect())
|
||||
}
|
||||
|
||||
/// 组合过滤搜索(懒加载):仅返回符合条件的相册,避免全量加载
|
||||
///
|
||||
/// 支持按 tag / person / 标题关键词 任意组合过滤(AND 关系)。
|
||||
/// 参数传空字符串或 None 表示不过滤该维度。
|
||||
/// 全参数为空时等价于 get_all_albums。
|
||||
pub async fn search_albums_with_filters(
|
||||
&self,
|
||||
tag: Option<&str>,
|
||||
person: Option<&str>,
|
||||
title_q: Option<&str>,
|
||||
limit: i64,
|
||||
offset: i64,
|
||||
) -> Result<Vec<AlbumInfo>, sqlx::Error> {
|
||||
let has_tag = tag.map(|s| !s.is_empty()).unwrap_or(false);
|
||||
let has_person = person.map(|s| !s.is_empty()).unwrap_or(false);
|
||||
let has_q = title_q.map(|s| !s.is_empty()).unwrap_or(false);
|
||||
|
||||
if !has_tag && !has_person && !has_q {
|
||||
// 无过滤条件 → 走缓存路径,这里回退到全量查询
|
||||
return self.get_all_albums().await;
|
||||
}
|
||||
|
||||
// 动态构建 SQL
|
||||
let sql = {
|
||||
let mut s = String::from(
|
||||
"SELECT DISTINCT a.id, a.title, a.document, a.description, \
|
||||
a.cover_image_id, a.image_count, a.created_at \
|
||||
FROM albums a"
|
||||
);
|
||||
let mut joins = Vec::new();
|
||||
let mut wheres = Vec::new();
|
||||
|
||||
if has_tag {
|
||||
joins.push("JOIN album_tags t ON a.id = t.album_id");
|
||||
wheres.push("t.tag = ?");
|
||||
}
|
||||
if has_person {
|
||||
joins.push("JOIN person_albums pa ON a.id = pa.album_id");
|
||||
joins.push("JOIN persons p ON pa.person_id = p.id");
|
||||
wheres.push("(p.name = ? OR p.name LIKE ?)");
|
||||
}
|
||||
if has_q {
|
||||
wheres.push("a.title LIKE ?");
|
||||
}
|
||||
|
||||
for j in &joins {
|
||||
s.push(' ');
|
||||
s.push_str(j);
|
||||
}
|
||||
if !wheres.is_empty() {
|
||||
s.push_str(" WHERE ");
|
||||
s.push_str(&wheres.join(" AND "));
|
||||
}
|
||||
s.push_str(" ORDER BY a.created_at DESC");
|
||||
|
||||
if limit > 0 {
|
||||
s.push_str(" LIMIT ? OFFSET ?");
|
||||
}
|
||||
|
||||
s
|
||||
};
|
||||
|
||||
let mut q = sqlx::query(&sql);
|
||||
|
||||
if has_tag {
|
||||
q = q.bind(tag.unwrap());
|
||||
}
|
||||
if has_person {
|
||||
let p = person.unwrap();
|
||||
q = q.bind(p).bind(format!("%{}%", p));
|
||||
}
|
||||
if has_q {
|
||||
q = q.bind(format!("%{}%", title_q.unwrap()));
|
||||
}
|
||||
if limit > 0 {
|
||||
q = q.bind(limit).bind(offset);
|
||||
}
|
||||
|
||||
let rows = q.fetch_all(&self.pool).await?;
|
||||
Ok(rows.iter().map(|r| {
|
||||
AlbumInfo {
|
||||
id: Uuid::parse_str(&r.get::<String, _>("id")).unwrap_or_else(|_| Uuid::nil()),
|
||||
title: r.get("title"),
|
||||
document: r.get("document"),
|
||||
description: r.get("description"),
|
||||
cover_image_id: r.get("cover_image_id"),
|
||||
image_count: r.get("image_count"),
|
||||
created_at: r.get("created_at"),
|
||||
}
|
||||
}).collect())
|
||||
}
|
||||
|
||||
pub async fn get_album_with_images(&self, album_id: Uuid) -> Result<Option<AlbumWithImages>, sqlx::Error> {
|
||||
let row = sqlx::query("SELECT * FROM albums WHERE id = ?")
|
||||
.bind(album_id.to_string())
|
||||
|
||||
@@ -52,6 +52,8 @@ pub struct PersonRulesDef {
|
||||
pub prefixes: Vec<String>,
|
||||
#[serde(default)]
|
||||
pub excluded: Vec<String>,
|
||||
#[serde(default)]
|
||||
pub include: Vec<String>,
|
||||
}
|
||||
|
||||
// ── 运行时词典结构 ──
|
||||
@@ -79,6 +81,8 @@ pub struct TagDict {
|
||||
pub person_prefixes: Vec<String>,
|
||||
/// 排除的人物名(工作室/平台名,匹配上的人和包含这些词的人直接删除重解析)
|
||||
pub excluded_person_names: HashSet<String>,
|
||||
/// 强制包含的人物名(已知模特/演员名,只要出现就优先识别为人名)
|
||||
pub included_person_names: HashSet<String>,
|
||||
}
|
||||
|
||||
impl Default for TagDict {
|
||||
@@ -89,6 +93,7 @@ impl Default for TagDict {
|
||||
stop_words: HashSet::new(),
|
||||
person_prefixes: Vec::new(),
|
||||
excluded_person_names: HashSet::new(),
|
||||
included_person_names: HashSet::new(),
|
||||
};
|
||||
dict.fill_builtin();
|
||||
dict
|
||||
@@ -124,9 +129,13 @@ impl TagDict {
|
||||
}
|
||||
};
|
||||
|
||||
let (person_prefixes, excluded_person_names) = match file.person_rules {
|
||||
Some(rules) => (rules.prefixes, rules.excluded.into_iter().collect()),
|
||||
None => (Vec::new(), HashSet::new()),
|
||||
let (person_prefixes, excluded_person_names, included_person_names) = match file.person_rules {
|
||||
Some(rules) => (
|
||||
rules.prefixes,
|
||||
rules.excluded.into_iter().collect(),
|
||||
rules.include.into_iter().collect(),
|
||||
),
|
||||
None => (Vec::new(), HashSet::new(), HashSet::new()),
|
||||
};
|
||||
|
||||
let mut dict = TagDict {
|
||||
@@ -135,6 +144,7 @@ impl TagDict {
|
||||
stop_words: file.stop_words.into_iter().collect(),
|
||||
person_prefixes,
|
||||
excluded_person_names,
|
||||
included_person_names,
|
||||
};
|
||||
|
||||
for (cat_name, def) in file.tags {
|
||||
@@ -258,6 +268,18 @@ impl TagDict {
|
||||
&self.excluded_person_names
|
||||
}
|
||||
|
||||
/// 判断人名是否在强制包含列表中(应优先识别为人名)
|
||||
pub fn is_included_person(&self, name: &str) -> bool {
|
||||
let name_lower = name.to_lowercase();
|
||||
self.included_person_names.contains(name)
|
||||
|| self.included_person_names.contains(&name_lower)
|
||||
}
|
||||
|
||||
/// 获取强制包含人名集合
|
||||
pub fn get_included_persons(&self) -> &HashSet<String> {
|
||||
&self.included_person_names
|
||||
}
|
||||
|
||||
/// 内置回退
|
||||
fn fill_builtin(&mut self) {
|
||||
let builtin = vec![
|
||||
@@ -328,9 +350,15 @@ impl TagDict {
|
||||
"LeiLei", "Tristana", "Av",
|
||||
];
|
||||
|
||||
let included: Vec<&str> = vec![
|
||||
"杨晨晨", "水淼", "轩美宣", "王馨瑶",
|
||||
"雪儿", "曼曼", "佳佳", "小乔",
|
||||
];
|
||||
|
||||
for w in &stop_words { self.stop_words.insert(w.to_string()); }
|
||||
self.person_prefixes = person_prefixes.iter().map(|s| s.to_string()).collect();
|
||||
for n in &excluded { self.excluded_person_names.insert(n.to_string()); }
|
||||
for n in &included { self.included_person_names.insert(n.to_string()); }
|
||||
|
||||
for (name, label, bg, fg, words) in builtin {
|
||||
let ws: Vec<String> = words.iter().map(|w| w.to_string()).collect();
|
||||
@@ -359,9 +387,10 @@ pub fn reload_tag_dict() -> String {
|
||||
let mut dict = TAG_DICT.write().expect("tag_dict 锁被污染");
|
||||
dict.reload();
|
||||
format!(
|
||||
"词典已重载: {} 分类, {} 标签, {} 停用词, {} 前缀, {} 排除人名",
|
||||
"词典已重载: {} 分类, {} 标签, {} 停用词, {} 前缀, {} 排除人名, {} 包含人名",
|
||||
dict.categories.len(), dict.tag_to_category.len(),
|
||||
dict.stop_words.len(), dict.person_prefixes.len(), dict.excluded_person_names.len(),
|
||||
dict.included_person_names.len(),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -369,8 +398,9 @@ pub fn reload_tag_dict() -> String {
|
||||
pub fn get_tag_dict_stats() -> String {
|
||||
let dict = get_tag_dict();
|
||||
format!(
|
||||
"标签词典: {} 分类, {} 标签, {} 停用词, {} 前缀, {} 排除人名 | 文件: dict/tags.json",
|
||||
"标签词典: {} 分类, {} 标签, {} 停用词, {} 前缀, {} 排除人名, {} 包含人名 | 文件: dict/tags.json",
|
||||
dict.categories.len(), dict.tag_to_category.len(),
|
||||
dict.stop_words.len(), dict.person_prefixes.len(), dict.excluded_person_names.len(),
|
||||
dict.included_person_names.len(),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -289,6 +289,11 @@ pub fn is_excluded_name(name: &str) -> bool {
|
||||
pub fn is_likely_person_name(name: &str) -> bool {
|
||||
let name = name.trim();
|
||||
if name.is_empty() { return false; }
|
||||
|
||||
// 强制包含名单优先放行(已知模特名,跳过所有启发式检查)
|
||||
let dict = tag_dict::get_tag_dict();
|
||||
if dict.is_included_person(name) { return true; }
|
||||
|
||||
// 字符数必须 >= 3(人名至少需要 2 个中文字或 3 个英文字母)
|
||||
if name.chars().count() <= 2 { return false; }
|
||||
|
||||
|
||||
@@ -7,38 +7,68 @@ use std::sync::Arc;
|
||||
use tokio::sync::RwLock;
|
||||
use uuid::Uuid;
|
||||
|
||||
/// GET /api/albums — 从缓存返回全量相册(无过滤时)
|
||||
pub async fn get_albums(cache: web::Data<Arc<RwLock<AlbumsCache>>>) -> impl Responder {
|
||||
let c = cache.read().await;
|
||||
HttpResponse::Ok().json(&c.albums)
|
||||
}
|
||||
|
||||
/// GET /api/search — 组合搜索(支持 tag/person/q 过滤)
|
||||
///
|
||||
/// 参数:
|
||||
/// - q: 关键词(标题模糊匹配)
|
||||
/// - tag: 标签名(精确匹配)
|
||||
/// - person: 人物名(精确或模糊匹配)
|
||||
/// - page: 页码(默认 1)
|
||||
/// - limit: 每页条数(默认 50,最大 200)
|
||||
///
|
||||
/// 规则:有任意过滤条件时 → 走 DB 懒加载(只查符合条件的相册)
|
||||
/// 无过滤条件时 → 走缓存全量返回
|
||||
pub async fn search_albums(
|
||||
db: web::Data<Arc<Database>>,
|
||||
cache: web::Data<Arc<RwLock<AlbumsCache>>>,
|
||||
query: web::Query<HashMap<String, String>>,
|
||||
) -> impl Responder {
|
||||
let q = query.get("q").map(|s| s.as_str()).unwrap_or("");
|
||||
if q.len() > 100 { return HttpResponse::BadRequest().json(serde_json::json!({"error": "搜索查询过长"})); }
|
||||
if q.chars().any(|c| c.is_control() || c == '\0') { return HttpResponse::BadRequest().json(serde_json::json!({"error": "无效字符"})); }
|
||||
let tag = query.get("tag").map(|s| s.as_str()).unwrap_or("");
|
||||
let person = query.get("person").map(|s| s.as_str()).unwrap_or("");
|
||||
|
||||
let page: usize = query.get("page").and_then(|s| s.parse().ok()).unwrap_or(1);
|
||||
let limit: usize = query.get("limit").and_then(|s| s.parse().ok()).unwrap_or(50).min(200);
|
||||
let offset = (page - 1) * limit;
|
||||
// 校验
|
||||
let err = |msg: &str| HttpResponse::BadRequest().json(serde_json::json!({"error": msg}));
|
||||
if q.len() > 100 { return err("搜索查询过长"); }
|
||||
if q.chars().any(|c| c.is_control() || c == '\0') { return err("无效字符"); }
|
||||
|
||||
let has_filter = !q.is_empty() || !tag.is_empty() || !person.is_empty();
|
||||
|
||||
if has_filter {
|
||||
// ── 有过滤条件:走 DB 懒加载 ──
|
||||
let page: i64 = query.get("page").and_then(|s| s.parse().ok()).unwrap_or(1);
|
||||
let limit: i64 = query.get("limit").and_then(|s| s.parse().ok()).unwrap_or(50).min(200);
|
||||
let offset = (page - 1) * limit;
|
||||
|
||||
let tag_arg = if tag.is_empty() { None } else { Some(tag) };
|
||||
let person_arg = if person.is_empty() { None } else { Some(person) };
|
||||
let q_arg = if q.is_empty() { None } else { Some(q) };
|
||||
|
||||
match db.search_albums_with_filters(tag_arg, person_arg, q_arg, limit, offset).await {
|
||||
Ok(results) => HttpResponse::Ok().json(results),
|
||||
Err(e) => HttpResponse::InternalServerError().json(serde_json::json!({"error": format!("{}", e)})),
|
||||
}
|
||||
} else {
|
||||
// ── 无过滤条件:走缓存(现有行为) ──
|
||||
let c = cache.read().await;
|
||||
|
||||
let page: usize = query.get("page").and_then(|s| s.parse().ok()).unwrap_or(1);
|
||||
let limit: usize = query.get("limit").and_then(|s| s.parse().ok()).unwrap_or(50).min(200);
|
||||
let offset = (page - 1) * limit;
|
||||
|
||||
let c = cache.read().await;
|
||||
let results = if q.is_empty() {
|
||||
let total = c.albums.len();
|
||||
let start = offset.min(total);
|
||||
let end = (offset + limit).min(total);
|
||||
c.albums[start..end].to_vec()
|
||||
} else {
|
||||
let mut results = c.search(q);
|
||||
let total = results.len();
|
||||
let start = offset.min(total);
|
||||
let end = (offset + limit).min(total);
|
||||
if start < end { results.drain(start..end).collect() } else { Vec::new() }
|
||||
};
|
||||
let results = c.albums[start..end].to_vec();
|
||||
|
||||
HttpResponse::Ok().json(results)
|
||||
HttpResponse::Ok().json(results)
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn get_random_album(cache: web::Data<Arc<RwLock<AlbumsCache>>>) -> impl Responder {
|
||||
@@ -62,4 +92,4 @@ pub async fn create_album(db: web::Data<Arc<Database>>, body: web::Json<CreateAl
|
||||
Ok(id) => HttpResponse::Created().json(serde_json::json!({"id": id})),
|
||||
Err(e) => HttpResponse::InternalServerError().json(serde_json::json!({"error": format!("{}", e)})),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,6 +25,7 @@ pub async fn dict_stats() -> impl Responder {
|
||||
"total_stop_words": dict.get_stop_words().len(),
|
||||
"person_prefixes": dict.get_person_prefixes(),
|
||||
"excluded_person_names": dict.excluded_person_names.iter().collect::<Vec<_>>(),
|
||||
"included_person_names": dict.included_person_names.iter().collect::<Vec<_>>(),
|
||||
}))
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user