tv完善弹幕以及各种焦点

This commit is contained in:
mtvpls
2026-05-30 01:01:37 +08:00
parent a880b65f35
commit e7558874bc
5 changed files with 375 additions and 48 deletions
+18 -13
View File
@@ -18,6 +18,13 @@ export function createEmptyFeatureAccessMap(): FeatureAccessMap {
}, {} as FeatureAccessMap);
}
function createFullFeatureAccessMap(): FeatureAccessMap {
return ALL_FEATURE_PERMISSION_KEYS.reduce((acc, key) => {
acc[key] = true;
return acc;
}, {} as FeatureAccessMap);
}
function isPrivilegedRole(role?: string) {
return role === 'owner' || role === 'admin';
}
@@ -25,10 +32,7 @@ function isPrivilegedRole(role?: string) {
async function getUserFeatureAccessMap(username: string): Promise<FeatureAccessMap> {
const storageType = process.env.NEXT_PUBLIC_STORAGE_TYPE || 'localstorage';
if (storageType === 'localstorage') {
return ALL_FEATURE_PERMISSION_KEYS.reduce((acc, key) => {
acc[key] = true;
return acc;
}, {} as FeatureAccessMap);
return createFullFeatureAccessMap();
}
const userInfo = await db.getUserInfoV2(username);
@@ -37,10 +41,7 @@ async function getUserFeatureAccessMap(username: string): Promise<FeatureAccessM
}
if (username === process.env.USERNAME || isPrivilegedRole(userInfo.role)) {
return ALL_FEATURE_PERMISSION_KEYS.reduce((acc, key) => {
acc[key] = true;
return acc;
}, {} as FeatureAccessMap);
return createFullFeatureAccessMap();
}
const config = await getConfig();
@@ -48,10 +49,7 @@ async function getUserFeatureAccessMap(username: string): Promise<FeatureAccessM
// 兼容旧用户:未分配用户组时,默认拥有全部功能权限
if (tags.length === 0) {
return ALL_FEATURE_PERMISSION_KEYS.reduce((acc, key) => {
acc[key] = true;
return acc;
}, {} as FeatureAccessMap);
return createFullFeatureAccessMap();
}
const allowedPermissions = new Set<FeaturePermissionKey>();
@@ -71,7 +69,14 @@ async function getUserFeatureAccessMap(username: string): Promise<FeatureAccessM
export async function getUserFeatureAccess(username?: string | null): Promise<FeatureAccessMap> {
if (!username) return createEmptyFeatureAccessMap();
return getUserFeatureAccessMap(username);
try {
return await getUserFeatureAccessMap(username);
} catch (error) {
console.error('[Permissions] Failed to load feature access:', error);
return username === process.env.USERNAME
? createFullFeatureAccessMap()
: createEmptyFeatureAccessMap();
}
}
export async function hasFeaturePermission(
+25 -3
View File
@@ -5,10 +5,27 @@ import { Redis } from '@upstash/redis';
import { UpstashRedisAdapter } from './redis-adapter';
import { BaseRedisStorage } from './redis-base.db';
const DEFAULT_UPSTASH_TIMEOUT_MS =
process.env.NODE_ENV === 'development' ? 2500 : 8000;
const UPSTASH_TIMEOUT_MS = Math.max(
1000,
Number(process.env.UPSTASH_TIMEOUT_MS || DEFAULT_UPSTASH_TIMEOUT_MS)
);
const DEFAULT_UPSTASH_RETRIES =
process.env.NODE_ENV === 'development' ? 1 : 3;
const UPSTASH_MAX_RETRIES = Math.max(
1,
Number(process.env.UPSTASH_MAX_RETRIES || DEFAULT_UPSTASH_RETRIES)
);
function createUpstashAbortSignal() {
return AbortSignal.timeout(UPSTASH_TIMEOUT_MS);
}
// 添加Upstash Redis操作重试包装器
async function withRetry<T>(
operation: () => Promise<T>,
maxRetries = 3
maxRetries = UPSTASH_MAX_RETRIES
): Promise<T> {
for (let i = 0; i < maxRetries; i++) {
try {
@@ -19,6 +36,10 @@ async function withRetry<T>(
err.message?.includes('Connection') ||
err.message?.includes('ECONNREFUSED') ||
err.message?.includes('ENOTFOUND') ||
err.name === 'AbortError' ||
err.name === 'TimeoutError' ||
err.message?.includes('Aborted') ||
err.message?.includes('Timeout') ||
err.code === 'ECONNRESET' ||
err.code === 'EPIPE' ||
err.name === 'UpstashError';
@@ -68,11 +89,12 @@ function getUpstashRedisClient(): Redis {
client = new Redis({
url: upstashUrl,
token: upstashToken,
signal: createUpstashAbortSignal,
// 可选配置
retry: {
retries: 3,
retries: UPSTASH_MAX_RETRIES,
backoff: (retryCount: number) =>
Math.min(1000 * Math.pow(2, retryCount), 30000),
Math.min(500 * Math.pow(2, retryCount), 5000),
},
});