mirror of
https://github.com/MoonTechLab/LunaTV.git
synced 2026-03-02 17:27:31 +08:00
feat: admin api cookie
This commit is contained in:
57
src/lib/auth.ts
Normal file
57
src/lib/auth.ts
Normal file
@@ -0,0 +1,57 @@
|
||||
import { NextRequest } from 'next/server';
|
||||
|
||||
// 从cookie获取认证信息 (服务端使用)
|
||||
export function getAuthInfoFromCookie(request: NextRequest): {
|
||||
password?: string;
|
||||
username?: string;
|
||||
signature?: string;
|
||||
timestamp?: number;
|
||||
} | null {
|
||||
const authCookie = request.cookies.get('auth');
|
||||
|
||||
if (!authCookie) {
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
const decoded = decodeURIComponent(authCookie.value);
|
||||
const authData = JSON.parse(decoded);
|
||||
return authData;
|
||||
} catch (error) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// 从cookie获取认证信息 (客户端使用)
|
||||
export function getAuthInfoFromBrowserCookie(): {
|
||||
password?: string;
|
||||
username?: string;
|
||||
signature?: string;
|
||||
timestamp?: number;
|
||||
} | null {
|
||||
if (typeof window === 'undefined') {
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
// 解析 document.cookie
|
||||
const cookies = document.cookie.split(';').reduce((acc, cookie) => {
|
||||
const [key, value] = cookie.trim().split('=');
|
||||
if (key && value) {
|
||||
acc[key] = value;
|
||||
}
|
||||
return acc;
|
||||
}, {} as Record<string, string>);
|
||||
|
||||
const authCookie = cookies['auth'];
|
||||
if (!authCookie) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const decoded = decodeURIComponent(authCookie);
|
||||
const authData = JSON.parse(decoded);
|
||||
return authData;
|
||||
} catch (error) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -24,27 +24,11 @@ export interface PlayRecord {
|
||||
play_time: number; // 播放进度(秒)
|
||||
total_time: number; // 总进度(秒)
|
||||
save_time: number; // 记录保存时间(时间戳)
|
||||
user_id: number; // 用户 ID,本地存储情况下恒为 0
|
||||
}
|
||||
|
||||
// ---- 常量 ----
|
||||
const PLAY_RECORDS_KEY = 'moontv_play_records';
|
||||
|
||||
// +++ 新增:获取当前用户名工具函数 +++
|
||||
/**
|
||||
* 从 localStorage 中读取当前用户名
|
||||
* 如果不存在则返回 undefined
|
||||
*/
|
||||
function getUsername(): string | undefined {
|
||||
if (typeof window === 'undefined') return undefined;
|
||||
try {
|
||||
const name = localStorage.getItem('username')?.trim();
|
||||
return name || undefined;
|
||||
} catch {
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
// ---- 环境变量 ----
|
||||
const STORAGE_TYPE = (() => {
|
||||
const raw =
|
||||
@@ -84,10 +68,7 @@ export function generateStorageKey(source: string, id: string): string {
|
||||
export async function getAllPlayRecords(): Promise<Record<string, PlayRecord>> {
|
||||
// 若配置标明使用数据库,则从后端 API 拉取
|
||||
if (STORAGE_TYPE !== 'localstorage') {
|
||||
const user = getUsername();
|
||||
return fetchFromApi<Record<string, PlayRecord>>(
|
||||
`/api/playrecords?user=${encodeURIComponent(user ?? '')}`
|
||||
);
|
||||
return fetchFromApi<Record<string, PlayRecord>>(`/api/playrecords`);
|
||||
}
|
||||
|
||||
// 默认 / localstorage 流程
|
||||
@@ -112,21 +93,19 @@ export async function getAllPlayRecords(): Promise<Record<string, PlayRecord>> {
|
||||
export async function savePlayRecord(
|
||||
source: string,
|
||||
id: string,
|
||||
record: Omit<PlayRecord, 'user_id'>
|
||||
record: PlayRecord
|
||||
): Promise<void> {
|
||||
const key = generateStorageKey(source, id);
|
||||
const fullRecord: PlayRecord = { ...record, user_id: 0 };
|
||||
|
||||
// 若配置标明使用数据库,则通过 API 保存
|
||||
if (STORAGE_TYPE !== 'localstorage') {
|
||||
try {
|
||||
const user = getUsername();
|
||||
const res = await fetch('/api/playrecords', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify({ user, key, record: fullRecord }),
|
||||
body: JSON.stringify({ key, record }),
|
||||
});
|
||||
if (!res.ok) throw new Error(`保存播放记录失败: ${res.status}`);
|
||||
} catch (err) {
|
||||
@@ -144,7 +123,7 @@ export async function savePlayRecord(
|
||||
|
||||
try {
|
||||
const allRecords = await getAllPlayRecords();
|
||||
allRecords[key] = fullRecord;
|
||||
allRecords[key] = record;
|
||||
localStorage.setItem(PLAY_RECORDS_KEY, JSON.stringify(allRecords));
|
||||
} catch (err) {
|
||||
console.error('保存播放记录失败:', err);
|
||||
@@ -165,9 +144,7 @@ export async function deletePlayRecord(
|
||||
if (STORAGE_TYPE !== 'localstorage') {
|
||||
try {
|
||||
const res = await fetch(
|
||||
`/api/playrecords?key=${encodeURIComponent(
|
||||
key
|
||||
)}&user=${encodeURIComponent(getUsername() ?? '')}`,
|
||||
`/api/playrecords?key=${encodeURIComponent(key)}`,
|
||||
{
|
||||
method: 'DELETE',
|
||||
}
|
||||
@@ -206,10 +183,7 @@ export async function getSearchHistory(): Promise<string[]> {
|
||||
// 如果配置为使用数据库,则从后端 API 获取
|
||||
if (STORAGE_TYPE !== 'localstorage') {
|
||||
try {
|
||||
const user = getUsername();
|
||||
return fetchFromApi<string[]>(
|
||||
`/api/searchhistory?user=${encodeURIComponent(user ?? '')}`
|
||||
);
|
||||
return fetchFromApi<string[]>(`/api/searchhistory`);
|
||||
} catch (err) {
|
||||
console.error('获取搜索历史失败:', err);
|
||||
return [];
|
||||
@@ -243,13 +217,12 @@ export async function addSearchHistory(keyword: string): Promise<void> {
|
||||
// 数据库模式
|
||||
if (STORAGE_TYPE !== 'localstorage') {
|
||||
try {
|
||||
const user = getUsername();
|
||||
await fetch('/api/searchhistory', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify({ keyword: trimmed, user: user ?? '' }),
|
||||
body: JSON.stringify({ keyword: trimmed }),
|
||||
});
|
||||
} catch (err) {
|
||||
console.error('保存搜索历史失败:', err);
|
||||
@@ -280,8 +253,7 @@ export async function clearSearchHistory(): Promise<void> {
|
||||
// 数据库模式
|
||||
if (STORAGE_TYPE !== 'localstorage') {
|
||||
try {
|
||||
const user = getUsername();
|
||||
await fetch(`/api/searchhistory?user=${encodeURIComponent(user ?? '')}`, {
|
||||
await fetch(`/api/searchhistory`, {
|
||||
method: 'DELETE',
|
||||
});
|
||||
} catch (err) {
|
||||
@@ -305,15 +277,9 @@ export async function deleteSearchHistory(keyword: string): Promise<void> {
|
||||
// 数据库模式
|
||||
if (STORAGE_TYPE !== 'localstorage') {
|
||||
try {
|
||||
const user = getUsername();
|
||||
await fetch(
|
||||
`/api/searchhistory?user=${encodeURIComponent(
|
||||
user ?? ''
|
||||
)}&keyword=${encodeURIComponent(trimmed)}`,
|
||||
{
|
||||
method: 'DELETE',
|
||||
}
|
||||
);
|
||||
await fetch(`/api/searchhistory?keyword=${encodeURIComponent(trimmed)}`, {
|
||||
method: 'DELETE',
|
||||
});
|
||||
} catch (err) {
|
||||
console.error('删除搜索历史失败:', err);
|
||||
}
|
||||
@@ -342,7 +308,6 @@ export interface Favorite {
|
||||
cover: string;
|
||||
total_episodes: number;
|
||||
save_time: number;
|
||||
user_id: number; // 本地存储情况下恒为 0
|
||||
}
|
||||
|
||||
// 收藏在 localStorage 中使用的 key
|
||||
@@ -354,10 +319,7 @@ const FAVORITES_KEY = 'moontv_favorites';
|
||||
export async function getAllFavorites(): Promise<Record<string, Favorite>> {
|
||||
// 数据库模式
|
||||
if (STORAGE_TYPE !== 'localstorage') {
|
||||
const user = getUsername();
|
||||
return fetchFromApi<Record<string, Favorite>>(
|
||||
`/api/favorites?user=${encodeURIComponent(user ?? '')}`
|
||||
);
|
||||
return fetchFromApi<Record<string, Favorite>>(`/api/favorites`);
|
||||
}
|
||||
|
||||
// localStorage 模式
|
||||
@@ -381,21 +343,19 @@ export async function getAllFavorites(): Promise<Record<string, Favorite>> {
|
||||
export async function saveFavorite(
|
||||
source: string,
|
||||
id: string,
|
||||
favorite: Omit<Favorite, 'user_id'>
|
||||
favorite: Favorite
|
||||
): Promise<void> {
|
||||
const key = generateStorageKey(source, id);
|
||||
const fullFavorite: Favorite = { ...favorite, user_id: 0 };
|
||||
|
||||
// 数据库模式
|
||||
if (STORAGE_TYPE !== 'localstorage') {
|
||||
try {
|
||||
const user = getUsername();
|
||||
const res = await fetch('/api/favorites', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify({ user, key, favorite: fullFavorite }),
|
||||
body: JSON.stringify({ key, favorite }),
|
||||
});
|
||||
if (!res.ok) throw new Error(`保存收藏失败: ${res.status}`);
|
||||
} catch (err) {
|
||||
@@ -413,7 +373,7 @@ export async function saveFavorite(
|
||||
|
||||
try {
|
||||
const allFavorites = await getAllFavorites();
|
||||
allFavorites[key] = fullFavorite;
|
||||
allFavorites[key] = favorite;
|
||||
localStorage.setItem(FAVORITES_KEY, JSON.stringify(allFavorites));
|
||||
} catch (err) {
|
||||
console.error('保存收藏失败:', err);
|
||||
@@ -433,15 +393,9 @@ export async function deleteFavorite(
|
||||
// 数据库模式
|
||||
if (STORAGE_TYPE !== 'localstorage') {
|
||||
try {
|
||||
const user = getUsername();
|
||||
const res = await fetch(
|
||||
`/api/favorites?key=${encodeURIComponent(
|
||||
key
|
||||
)}&user=${encodeURIComponent(user ?? '')}`,
|
||||
{
|
||||
method: 'DELETE',
|
||||
}
|
||||
);
|
||||
const res = await fetch(`/api/favorites?key=${encodeURIComponent(key)}`, {
|
||||
method: 'DELETE',
|
||||
});
|
||||
if (!res.ok) throw new Error(`删除收藏失败: ${res.status}`);
|
||||
} catch (err) {
|
||||
console.error('删除收藏到数据库失败:', err);
|
||||
@@ -478,12 +432,7 @@ export async function isFavorited(
|
||||
// 数据库模式
|
||||
if (STORAGE_TYPE !== 'localstorage') {
|
||||
try {
|
||||
const user = getUsername();
|
||||
const res = await fetch(
|
||||
`/api/favorites?key=${encodeURIComponent(
|
||||
key
|
||||
)}&user=${encodeURIComponent(user ?? '')}`
|
||||
);
|
||||
const res = await fetch(`/api/favorites?key=${encodeURIComponent(key)}`);
|
||||
if (!res.ok) return false;
|
||||
const data = await res.json();
|
||||
return !!data;
|
||||
@@ -505,7 +454,7 @@ export async function isFavorited(
|
||||
export async function toggleFavorite(
|
||||
source: string,
|
||||
id: string,
|
||||
favoriteData?: Omit<Favorite, 'user_id'>
|
||||
favoriteData?: Favorite
|
||||
): Promise<boolean> {
|
||||
const already = await isFavorited(source, id);
|
||||
|
||||
@@ -528,9 +477,8 @@ export async function toggleFavorite(
|
||||
export async function clearAllPlayRecords(): Promise<void> {
|
||||
// 数据库模式
|
||||
if (STORAGE_TYPE !== 'localstorage') {
|
||||
const user = getUsername();
|
||||
try {
|
||||
await fetch(`/api/playrecords?user=${encodeURIComponent(user ?? '')}`, {
|
||||
await fetch(`/api/playrecords`, {
|
||||
method: 'DELETE',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
});
|
||||
@@ -551,9 +499,8 @@ export async function clearAllPlayRecords(): Promise<void> {
|
||||
export async function clearAllFavorites(): Promise<void> {
|
||||
// 数据库模式
|
||||
if (STORAGE_TYPE !== 'localstorage') {
|
||||
const user = getUsername();
|
||||
try {
|
||||
await fetch(`/api/favorites?user=${encodeURIComponent(user ?? '')}`, {
|
||||
await fetch(`/api/favorites`, {
|
||||
method: 'DELETE',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
});
|
||||
|
||||
@@ -63,8 +63,7 @@ export class DbManager {
|
||||
record: Omit<PlayRecord, 'user_id'>
|
||||
): Promise<void> {
|
||||
const key = generateStorageKey(source, id);
|
||||
const fullRecord: PlayRecord = { ...record, user_id: 0 };
|
||||
await this.storage.setPlayRecord(userName, key, fullRecord);
|
||||
await this.storage.setPlayRecord(userName, key, record);
|
||||
}
|
||||
|
||||
async getAllPlayRecords(userName: string): Promise<{
|
||||
@@ -96,11 +95,10 @@ export class DbManager {
|
||||
userName: string,
|
||||
source: string,
|
||||
id: string,
|
||||
favorite: Omit<Favorite, 'user_id'>
|
||||
favorite: Favorite
|
||||
): Promise<void> {
|
||||
const key = generateStorageKey(source, id);
|
||||
const fullFavorite: Favorite = { ...favorite, user_id: 0 };
|
||||
await this.storage.setFavorite(userName, key, fullFavorite);
|
||||
await this.storage.setFavorite(userName, key, favorite);
|
||||
}
|
||||
|
||||
async getAllFavorites(
|
||||
|
||||
@@ -10,7 +10,6 @@ export interface PlayRecord {
|
||||
play_time: number; // 播放进度(秒)
|
||||
total_time: number; // 总进度(秒)
|
||||
save_time: number; // 记录保存时间(时间戳)
|
||||
user_id: number; // 用户ID,localStorage情况下全部为0
|
||||
}
|
||||
|
||||
// 收藏数据结构
|
||||
@@ -19,7 +18,6 @@ export interface Favorite {
|
||||
total_episodes: number; // 总集数
|
||||
title: string;
|
||||
cover: string;
|
||||
user_id: number; // 用户ID,localStorage情况下全部为0
|
||||
save_time: number; // 记录保存时间(时间戳)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user