磁链增加代理配置

This commit is contained in:
mtvpls
2026-03-25 10:30:22 +08:00
parent f24c42cb90
commit cc1e70ad61
8 changed files with 219 additions and 10 deletions

View File

@@ -352,6 +352,10 @@ interface SiteConfig {
PansouUsername?: string;
PansouPassword?: string;
PansouKeywordBlocklist?: string;
MagnetProxy?: string;
MagnetMikanReverseProxy?: string;
MagnetDmhyReverseProxy?: string;
MagnetAcgripReverseProxy?: string;
EnableComments: boolean;
EnableRegistration?: boolean;
RegistrationRequireTurnstile?: boolean;
@@ -7921,12 +7925,17 @@ const SiteConfigComponent = ({
DanmakuApiToken: '87654321',
TMDBApiKey: '',
TMDBProxy: '',
TMDBReverseProxy: '',
BannerDataSource: 'Douban',
RecommendationDataSource: 'Mixed',
PansouApiUrl: '',
PansouUsername: '',
PansouPassword: '',
PansouKeywordBlocklist: '',
MagnetProxy: '',
MagnetMikanReverseProxy: '',
MagnetDmhyReverseProxy: '',
MagnetAcgripReverseProxy: '',
EnableComments: false,
EnableRegistration: false,
RegistrationRequireTurnstile: false,
@@ -8012,12 +8021,17 @@ const SiteConfigComponent = ({
DanmakuApiToken: config.SiteConfig.DanmakuApiToken || '87654321',
TMDBApiKey: config.SiteConfig.TMDBApiKey || '',
TMDBProxy: config.SiteConfig.TMDBProxy || '',
TMDBReverseProxy: config.SiteConfig.TMDBReverseProxy || '',
BannerDataSource: config.SiteConfig.BannerDataSource || 'Douban',
RecommendationDataSource: config.SiteConfig.RecommendationDataSource || 'Mixed',
PansouApiUrl: config.SiteConfig.PansouApiUrl || '',
PansouUsername: config.SiteConfig.PansouUsername || '',
PansouPassword: config.SiteConfig.PansouPassword || '',
PansouKeywordBlocklist: config.SiteConfig.PansouKeywordBlocklist || '',
MagnetProxy: config.SiteConfig.MagnetProxy || '',
MagnetMikanReverseProxy: config.SiteConfig.MagnetMikanReverseProxy || '',
MagnetDmhyReverseProxy: config.SiteConfig.MagnetDmhyReverseProxy || '',
MagnetAcgripReverseProxy: config.SiteConfig.MagnetAcgripReverseProxy || '',
EnableComments: config.SiteConfig.EnableComments || false,
});
}
@@ -8687,6 +8701,97 @@ const SiteConfigComponent = ({
</div>
</details>
<details className='pt-4 border-t border-gray-200 dark:border-gray-700'>
<summary className='text-sm font-semibold text-gray-900 dark:text-gray-100 cursor-pointer'>
</summary>
<div className='mt-4 space-y-4'>
<div>
<label className='block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2'>
</label>
<input
type='text'
placeholder='请输入代理地址(可选)'
value={siteSettings.MagnetProxy || ''}
onChange={(e) =>
setSiteSettings((prev) => ({
...prev,
MagnetProxy: e.target.value,
}))
}
className='w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-800 text-gray-900 dark:text-gray-100 focus:ring-2 focus:ring-green-500 focus:border-transparent'
/>
<p className='mt-1 text-xs text-gray-500 dark:text-gray-400'>
访Cloudflare 使
</p>
</div>
<div>
<label className='block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2'>
Mikan
</label>
<input
type='text'
placeholder='请输入 Mikan 反代 Base URL可选'
value={siteSettings.MagnetMikanReverseProxy || ''}
onChange={(e) =>
setSiteSettings((prev) => ({
...prev,
MagnetMikanReverseProxy: e.target.value,
}))
}
className='w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-800 text-gray-900 dark:text-gray-100 focus:ring-2 focus:ring-green-500 focus:border-transparent'
/>
<p className='mt-1 text-xs text-gray-500 dark:text-gray-400'>
使 Mikan
</p>
</div>
<div>
<label className='block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2'>
</label>
<input
type='text'
placeholder='请输入动漫花园反代 Base URL可选'
value={siteSettings.MagnetDmhyReverseProxy || ''}
onChange={(e) =>
setSiteSettings((prev) => ({
...prev,
MagnetDmhyReverseProxy: e.target.value,
}))
}
className='w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-800 text-gray-900 dark:text-gray-100 focus:ring-2 focus:ring-green-500 focus:border-transparent'
/>
<p className='mt-1 text-xs text-gray-500 dark:text-gray-400'>
使
</p>
</div>
<div>
<label className='block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2'>
ACG.RIP
</label>
<input
type='text'
placeholder='请输入 ACG.RIP 反代 Base URL可选'
value={siteSettings.MagnetAcgripReverseProxy || ''}
onChange={(e) =>
setSiteSettings((prev) => ({
...prev,
MagnetAcgripReverseProxy: e.target.value,
}))
}
className='w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-800 text-gray-900 dark:text-gray-100 focus:ring-2 focus:ring-green-500 focus:border-transparent'
/>
<p className='mt-1 text-xs text-gray-500 dark:text-gray-400'>
使 ACG.RIP
</p>
</div>
</div>
</details>
{/* Pansou 配置 */}
<details className='pt-4 border-t border-gray-200 dark:border-gray-700'>
<summary className='text-sm font-semibold text-gray-900 dark:text-gray-100 cursor-pointer'>

View File

@@ -3,6 +3,8 @@ import { NextRequest, NextResponse } from 'next/server';
import { parseStringPromise } from 'xml2js';
import { getAuthInfoFromCookie } from '@/lib/auth';
import { getConfig } from '@/lib/config';
import { getMagnetBaseUrl, universalMagnetFetch } from '@/lib/magnet.client';
export const runtime = 'nodejs';
@@ -48,11 +50,17 @@ export async function POST(req: NextRequest) {
}
// 请求 acg.rip RSS
const searchUrl = `https://acg.rip/page/${pageNum}.xml?term=${encodeURIComponent(trimmedKeyword)}`;
const config = await getConfig();
const searchBaseUrl = getMagnetBaseUrl(
'https://acg.rip',
config.SiteConfig.MagnetAcgripReverseProxy
);
const searchUrl = `${searchBaseUrl}/page/${pageNum}.xml?term=${encodeURIComponent(trimmedKeyword)}`;
const response = await fetch(searchUrl, {
const response = await universalMagnetFetch(searchUrl, config.SiteConfig.MagnetProxy, {
headers: {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36',
'User-Agent':
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36',
},
});
@@ -123,4 +131,3 @@ export async function POST(req: NextRequest) {
);
}
}

View File

@@ -3,6 +3,8 @@ import { NextRequest, NextResponse } from 'next/server';
import { parseStringPromise } from 'xml2js';
import { getAuthInfoFromCookie } from '@/lib/auth';
import { getConfig } from '@/lib/config';
import { getMagnetBaseUrl, universalMagnetFetch } from '@/lib/magnet.client';
export const runtime = 'nodejs';
@@ -56,11 +58,15 @@ export async function POST(req: NextRequest) {
});
}
const baseUrl = 'http://share.dmhy.org/topics/rss/rss.xml';
const config = await getConfig();
const baseUrl = `${getMagnetBaseUrl(
'http://share.dmhy.org',
config.SiteConfig.MagnetDmhyReverseProxy
)}/topics/rss/rss.xml`;
const params = new URLSearchParams({ keyword: trimmedKeyword });
const searchUrl = `${baseUrl}?${params.toString()}`;
const response = await fetch(searchUrl, {
const response = await universalMagnetFetch(searchUrl, config.SiteConfig.MagnetProxy, {
headers: {
'User-Agent':
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36',

View File

@@ -3,6 +3,8 @@ import { NextRequest, NextResponse } from 'next/server';
import { parseStringPromise } from 'xml2js';
import { getAuthInfoFromCookie } from '@/lib/auth';
import { getConfig } from '@/lib/config';
import { getMagnetBaseUrl, universalMagnetFetch } from '@/lib/magnet.client';
export const runtime = 'nodejs';
@@ -62,11 +64,17 @@ export async function POST(req: NextRequest) {
});
}
const searchUrl = `https://mikanani.me/RSS/Search?searchstr=${encodeURIComponent(trimmedKeyword)}`;
const config = await getConfig();
const searchBaseUrl = getMagnetBaseUrl(
'https://mikanani.me',
config.SiteConfig.MagnetMikanReverseProxy
);
const searchUrl = `${searchBaseUrl}/RSS/Search?searchstr=${encodeURIComponent(trimmedKeyword)}`;
const response = await fetch(searchUrl, {
const response = await universalMagnetFetch(searchUrl, config.SiteConfig.MagnetProxy, {
headers: {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36',
'User-Agent':
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36',
},
});
@@ -144,4 +152,3 @@ export async function POST(req: NextRequest) {
);
}
}

View File

@@ -50,6 +50,10 @@ export async function POST(request: NextRequest) {
PansouUsername,
PansouPassword,
PansouKeywordBlocklist,
MagnetProxy,
MagnetMikanReverseProxy,
MagnetDmhyReverseProxy,
MagnetAcgripReverseProxy,
EnableComments,
CustomAdFilterCode,
CustomAdFilterVersion,
@@ -91,6 +95,10 @@ export async function POST(request: NextRequest) {
PansouUsername?: string;
PansouPassword?: string;
PansouKeywordBlocklist?: string;
MagnetProxy?: string;
MagnetMikanReverseProxy?: string;
MagnetDmhyReverseProxy?: string;
MagnetAcgripReverseProxy?: string;
EnableComments: boolean;
CustomAdFilterCode?: string;
CustomAdFilterVersion?: number;
@@ -132,6 +140,10 @@ export async function POST(request: NextRequest) {
(BannerDataSource !== undefined && typeof BannerDataSource !== 'string') ||
(RecommendationDataSource !== undefined && typeof RecommendationDataSource !== 'string') ||
(PansouKeywordBlocklist !== undefined && typeof PansouKeywordBlocklist !== 'string') ||
(MagnetProxy !== undefined && typeof MagnetProxy !== 'string') ||
(MagnetMikanReverseProxy !== undefined && typeof MagnetMikanReverseProxy !== 'string') ||
(MagnetDmhyReverseProxy !== undefined && typeof MagnetDmhyReverseProxy !== 'string') ||
(MagnetAcgripReverseProxy !== undefined && typeof MagnetAcgripReverseProxy !== 'string') ||
typeof EnableComments !== 'boolean' ||
(CustomAdFilterCode !== undefined && typeof CustomAdFilterCode !== 'string') ||
(CustomAdFilterVersion !== undefined && typeof CustomAdFilterVersion !== 'number') ||
@@ -188,6 +200,10 @@ export async function POST(request: NextRequest) {
PansouUsername,
PansouPassword,
PansouKeywordBlocklist,
MagnetProxy,
MagnetMikanReverseProxy,
MagnetDmhyReverseProxy,
MagnetAcgripReverseProxy,
EnableComments,
CustomAdFilterCode,
CustomAdFilterVersion,

View File

@@ -30,6 +30,11 @@ export interface AdminConfig {
PansouUsername?: string;
PansouPassword?: string;
PansouKeywordBlocklist?: string;
// 磁链配置
MagnetProxy?: string;
MagnetMikanReverseProxy?: string;
MagnetDmhyReverseProxy?: string;
MagnetAcgripReverseProxy?: string;
// 评论功能开关
EnableComments: boolean;
// 自定义去广告代码

View File

@@ -256,6 +256,11 @@ async function getInitConfig(configFile: string, subConfig: {
PansouUsername: '',
PansouPassword: '',
PansouKeywordBlocklist: '',
// 磁链配置
MagnetProxy: '',
MagnetMikanReverseProxy: '',
MagnetDmhyReverseProxy: '',
MagnetAcgripReverseProxy: '',
// 评论功能开关
EnableComments: false,
},
@@ -432,6 +437,10 @@ export function configSelfCheck(adminConfig: AdminConfig): AdminConfig {
PansouUsername: '',
PansouPassword: '',
PansouKeywordBlocklist: '',
MagnetProxy: '',
MagnetMikanReverseProxy: '',
MagnetDmhyReverseProxy: '',
MagnetAcgripReverseProxy: '',
EnableComments: false,
};
}
@@ -449,6 +458,18 @@ export function configSelfCheck(adminConfig: AdminConfig): AdminConfig {
if (adminConfig.SiteConfig.PansouKeywordBlocklist === undefined) {
adminConfig.SiteConfig.PansouKeywordBlocklist = '';
}
if (adminConfig.SiteConfig.MagnetProxy === undefined) {
adminConfig.SiteConfig.MagnetProxy = '';
}
if (adminConfig.SiteConfig.MagnetMikanReverseProxy === undefined) {
adminConfig.SiteConfig.MagnetMikanReverseProxy = '';
}
if (adminConfig.SiteConfig.MagnetDmhyReverseProxy === undefined) {
adminConfig.SiteConfig.MagnetDmhyReverseProxy = '';
}
if (adminConfig.SiteConfig.MagnetAcgripReverseProxy === undefined) {
adminConfig.SiteConfig.MagnetAcgripReverseProxy = '';
}
if (!adminConfig.UserConfig) {
adminConfig.UserConfig = { Users: [] };
}

42
src/lib/magnet.client.ts Normal file
View File

@@ -0,0 +1,42 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
import { HttpsProxyAgent } from 'https-proxy-agent';
import nodeFetch from 'node-fetch';
function isCloudflareEnvironment(): boolean {
return process.env.CF_PAGES === '1' || process.env.BUILD_TARGET === 'cloudflare';
}
export function getMagnetBaseUrl(defaultBaseUrl: string, reverseProxyBaseUrl?: string): string {
return (reverseProxyBaseUrl || defaultBaseUrl).replace(/\/+$/, '');
}
export async function universalMagnetFetch(
url: string,
proxy?: string,
init?: RequestInit
): Promise<Response> {
if (isCloudflareEnvironment()) {
const response = await fetch(url, {
...init,
signal: AbortSignal.timeout(15000),
});
return response as unknown as Response;
}
const fetchOptions: any = proxy
? {
...init,
agent: new HttpsProxyAgent(proxy, {
timeout: 30000,
keepAlive: false,
}),
signal: AbortSignal.timeout(30000),
}
: {
...init,
signal: AbortSignal.timeout(15000),
};
return nodeFetch(url, fetchOptions) as unknown as Response;
}