fix: 完善成人内容过滤功能的部署兼容性
- 为用户设置API添加Edge Runtime配置确保部署兼容性 - 完善所有存储后端的用户设置方法实现 - 为D1数据库添加user_settings表迁移脚本 - 修复TypeScript类型错误和构建兼容性 - 所有25个API路由现在都正确配置了Edge Runtime - 确保Docker、Cloudflare Pages等各平台部署正常运行
This commit is contained in:
@@ -4,6 +4,9 @@ import { NextRequest, NextResponse } from 'next/server';
|
||||
import { getStorage } from '@/lib/db';
|
||||
import { UserSettings } from '@/lib/types';
|
||||
|
||||
// 设置运行时为 Edge Runtime,确保部署兼容性
|
||||
export const runtime = 'edge';
|
||||
|
||||
// 获取用户设置
|
||||
export async function GET(_request: NextRequest) {
|
||||
try {
|
||||
|
||||
+60
-1
@@ -1,7 +1,7 @@
|
||||
/* eslint-disable no-console, @typescript-eslint/no-explicit-any, @typescript-eslint/no-non-null-assertion */
|
||||
|
||||
import { AdminConfig } from './admin.types';
|
||||
import { EpisodeSkipConfig, Favorite, IStorage, PlayRecord } from './types';
|
||||
import { EpisodeSkipConfig, Favorite, IStorage, PlayRecord, UserSettings } from './types';
|
||||
|
||||
// 搜索历史最大条数
|
||||
const SEARCH_HISTORY_LIMIT = 20;
|
||||
@@ -573,4 +573,63 @@ export class D1Storage implements IStorage {
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
|
||||
// ---------- 用户设置 ----------
|
||||
async getUserSettings(userName: string): Promise<UserSettings | null> {
|
||||
try {
|
||||
const db = await this.getDatabase();
|
||||
const row = await db
|
||||
.prepare('SELECT settings FROM user_settings WHERE username = ?')
|
||||
.bind(userName)
|
||||
.first();
|
||||
|
||||
if (row && row.settings) {
|
||||
return JSON.parse(row.settings as string) as UserSettings;
|
||||
}
|
||||
return null;
|
||||
} catch (err) {
|
||||
console.error('Failed to get user settings:', err);
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
|
||||
async setUserSettings(
|
||||
userName: string,
|
||||
settings: UserSettings
|
||||
): Promise<void> {
|
||||
try {
|
||||
const db = await this.getDatabase();
|
||||
await db
|
||||
.prepare(`
|
||||
INSERT OR REPLACE INTO user_settings (username, settings, updated_time)
|
||||
VALUES (?, ?, ?)
|
||||
`)
|
||||
.bind(userName, JSON.stringify(settings), Date.now())
|
||||
.run();
|
||||
} catch (err) {
|
||||
console.error('Failed to set user settings:', err);
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
|
||||
async updateUserSettings(
|
||||
userName: string,
|
||||
settings: Partial<UserSettings>
|
||||
): Promise<void> {
|
||||
const current = await this.getUserSettings(userName);
|
||||
const defaultSettings: UserSettings = {
|
||||
filter_adult_content: true,
|
||||
theme: 'auto',
|
||||
language: 'zh-CN',
|
||||
auto_play: false,
|
||||
video_quality: 'auto'
|
||||
};
|
||||
const updated: UserSettings = {
|
||||
...defaultSettings,
|
||||
...current,
|
||||
...settings,
|
||||
filter_adult_content: settings.filter_adult_content ?? current?.filter_adult_content ?? true
|
||||
};
|
||||
await this.setUserSettings(userName, updated);
|
||||
}
|
||||
}
|
||||
|
||||
+43
-1
@@ -3,7 +3,7 @@
|
||||
import { createClient, RedisClientType } from 'redis';
|
||||
|
||||
import { AdminConfig } from './admin.types';
|
||||
import { EpisodeSkipConfig, Favorite, IStorage, PlayRecord } from './types';
|
||||
import { EpisodeSkipConfig, Favorite, IStorage, PlayRecord, UserSettings } from './types';
|
||||
|
||||
// 搜索历史最大条数
|
||||
const SEARCH_HISTORY_LIMIT = 20;
|
||||
@@ -337,6 +337,48 @@ export class KvrocksStorage implements IStorage {
|
||||
this.client.set(this.adminConfigKey(), JSON.stringify(config))
|
||||
);
|
||||
}
|
||||
|
||||
// ---------- 用户设置 ----------
|
||||
private userSettingsKey(userName: string) {
|
||||
return `u:${userName}:settings`;
|
||||
}
|
||||
|
||||
async getUserSettings(userName: string): Promise<UserSettings | null> {
|
||||
const val = await withRetry(() =>
|
||||
this.client.get(this.userSettingsKey(userName))
|
||||
);
|
||||
return val ? (JSON.parse(val) as UserSettings) : null;
|
||||
}
|
||||
|
||||
async setUserSettings(
|
||||
userName: string,
|
||||
settings: UserSettings
|
||||
): Promise<void> {
|
||||
await withRetry(() =>
|
||||
this.client.set(this.userSettingsKey(userName), JSON.stringify(settings))
|
||||
);
|
||||
}
|
||||
|
||||
async updateUserSettings(
|
||||
userName: string,
|
||||
settings: Partial<UserSettings>
|
||||
): Promise<void> {
|
||||
const current = await this.getUserSettings(userName);
|
||||
const defaultSettings: UserSettings = {
|
||||
filter_adult_content: true,
|
||||
theme: 'auto',
|
||||
language: 'zh-CN',
|
||||
auto_play: false,
|
||||
video_quality: 'auto'
|
||||
};
|
||||
const updated: UserSettings = {
|
||||
...defaultSettings,
|
||||
...current,
|
||||
...settings,
|
||||
filter_adult_content: settings.filter_adult_content ?? current?.filter_adult_content ?? true
|
||||
};
|
||||
await this.setUserSettings(userName, updated);
|
||||
}
|
||||
}
|
||||
|
||||
// Kvrocks客户端单例
|
||||
|
||||
@@ -329,6 +329,48 @@ export class UpstashRedisStorage implements IStorage {
|
||||
await this.client.srem(this.skipConfigsKey(userName), key);
|
||||
});
|
||||
}
|
||||
|
||||
// ---------- 用户设置 ----------
|
||||
private userSettingsKey(userName: string) {
|
||||
return `u:${userName}:settings`;
|
||||
}
|
||||
|
||||
async getUserSettings(userName: string): Promise<UserSettings | null> {
|
||||
const val = await withRetry(() =>
|
||||
this.client.get(this.userSettingsKey(userName))
|
||||
);
|
||||
return val ? (val as UserSettings) : null;
|
||||
}
|
||||
|
||||
async setUserSettings(
|
||||
userName: string,
|
||||
settings: UserSettings
|
||||
): Promise<void> {
|
||||
await withRetry(() =>
|
||||
this.client.set(this.userSettingsKey(userName), settings)
|
||||
);
|
||||
}
|
||||
|
||||
async updateUserSettings(
|
||||
userName: string,
|
||||
settings: Partial<UserSettings>
|
||||
): Promise<void> {
|
||||
const current = await this.getUserSettings(userName);
|
||||
const defaultSettings: UserSettings = {
|
||||
filter_adult_content: true,
|
||||
theme: 'auto',
|
||||
language: 'zh-CN',
|
||||
auto_play: false,
|
||||
video_quality: 'auto'
|
||||
};
|
||||
const updated: UserSettings = {
|
||||
...defaultSettings,
|
||||
...current,
|
||||
...settings,
|
||||
filter_adult_content: settings.filter_adult_content ?? current?.filter_adult_content ?? true
|
||||
};
|
||||
await this.setUserSettings(userName, updated);
|
||||
}
|
||||
}
|
||||
|
||||
// 单例 Upstash Redis 客户端
|
||||
|
||||
Reference in New Issue
Block a user