增加漫画展馆功能
This commit is contained in:
@@ -3,6 +3,7 @@
|
||||
import { createClient, RedisClientType } from 'redis';
|
||||
|
||||
import { AdminConfig } from './admin.types';
|
||||
import { MangaReadRecord, MangaShelfItem } from './manga.types';
|
||||
import { MusicV2HistoryRecord, MusicV2PlaylistItem, MusicV2PlaylistRecord } from './music-v2';
|
||||
import { RedisAdapter } from './redis-adapter';
|
||||
import { Favorite, IStorage, PlayRecord, SkipConfig } from './types';
|
||||
@@ -1005,6 +1006,10 @@ export abstract class BaseRedisStorage implements IStorage {
|
||||
// 删除收藏夹(新hash结构)
|
||||
await this.withRetry(() => this.adapter.del(this.favHashKey(userName)));
|
||||
|
||||
// 删除漫画书架与历史
|
||||
await this.withRetry(() => this.adapter.del(this.mangaShelfHashKey(userName)));
|
||||
await this.withRetry(() => this.adapter.del(this.mangaReadHashKey(userName)));
|
||||
|
||||
// 删除旧的收藏key(如果有)
|
||||
const favoritePattern = `u:${userName}:fav:*`;
|
||||
const favoriteKeys = await this.withRetry(() =>
|
||||
@@ -1495,6 +1500,73 @@ export abstract class BaseRedisStorage implements IStorage {
|
||||
}
|
||||
}
|
||||
|
||||
// ---------- 漫画书架 ----------
|
||||
private mangaShelfHashKey(user: string) {
|
||||
return `u:${user}:manga:shelf`;
|
||||
}
|
||||
|
||||
async getMangaShelf(userName: string, key: string): Promise<MangaShelfItem | null> {
|
||||
const val = await this.withRetry(() => this.adapter.hGet(this.mangaShelfHashKey(userName), key));
|
||||
return val ? (JSON.parse(val) as MangaShelfItem) : null;
|
||||
}
|
||||
|
||||
async setMangaShelf(userName: string, key: string, item: MangaShelfItem): Promise<void> {
|
||||
await this.withRetry(() => this.adapter.hSet(this.mangaShelfHashKey(userName), key, JSON.stringify(item)));
|
||||
}
|
||||
|
||||
async getAllMangaShelf(userName: string): Promise<Record<string, MangaShelfItem>> {
|
||||
const hashData = await this.withRetry(() => this.adapter.hGetAll(this.mangaShelfHashKey(userName)));
|
||||
const result: Record<string, MangaShelfItem> = {};
|
||||
for (const [key, value] of Object.entries(hashData)) {
|
||||
if (value) result[key] = JSON.parse(value) as MangaShelfItem;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
async deleteMangaShelf(userName: string, key: string): Promise<void> {
|
||||
await this.withRetry(() => this.adapter.hDel(this.mangaShelfHashKey(userName), key));
|
||||
}
|
||||
|
||||
// ---------- 漫画阅读历史 ----------
|
||||
private mangaReadHashKey(user: string) {
|
||||
return `u:${user}:manga:history`;
|
||||
}
|
||||
|
||||
async getMangaReadRecord(userName: string, key: string): Promise<MangaReadRecord | null> {
|
||||
const val = await this.withRetry(() => this.adapter.hGet(this.mangaReadHashKey(userName), key));
|
||||
return val ? (JSON.parse(val) as MangaReadRecord) : null;
|
||||
}
|
||||
|
||||
async setMangaReadRecord(userName: string, key: string, record: MangaReadRecord): Promise<void> {
|
||||
await this.withRetry(() => this.adapter.hSet(this.mangaReadHashKey(userName), key, JSON.stringify(record)));
|
||||
}
|
||||
|
||||
async getAllMangaReadRecords(userName: string): Promise<Record<string, MangaReadRecord>> {
|
||||
const hashData = await this.withRetry(() => this.adapter.hGetAll(this.mangaReadHashKey(userName)));
|
||||
const result: Record<string, MangaReadRecord> = {};
|
||||
for (const [key, value] of Object.entries(hashData)) {
|
||||
if (value) result[key] = JSON.parse(value) as MangaReadRecord;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
async deleteMangaReadRecord(userName: string, key: string): Promise<void> {
|
||||
await this.withRetry(() => this.adapter.hDel(this.mangaReadHashKey(userName), key));
|
||||
}
|
||||
|
||||
async cleanupOldMangaReadRecords(userName: string): Promise<void> {
|
||||
const records = await this.getAllMangaReadRecords(userName);
|
||||
const maxRecords = parseInt(process.env.MAX_MANGA_HISTORY_PER_USER || '100', 10);
|
||||
const keys = Object.entries(records)
|
||||
.sort(([, a], [, b]) => b.saveTime - a.saveTime)
|
||||
.slice(maxRecords)
|
||||
.map(([key]) => key);
|
||||
|
||||
if (keys.length > 0) {
|
||||
await this.withRetry(() => this.adapter.hDel(this.mangaReadHashKey(userName), ...keys));
|
||||
}
|
||||
}
|
||||
|
||||
// ---------- 获取全部用户 ----------
|
||||
async getAllUsers(): Promise<string[]> {
|
||||
// 从新版用户列表获取
|
||||
|
||||
Reference in New Issue
Block a user