| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778 |
- const VOLATILE_IMAGE_HOSTS = new Set([
- 'finder.video.qq.com',
- ]);
- const VOLATILE_IMAGE_PATH_PARTS = [
- '/stodownload',
- ];
- const IMAGE_FIELD_KEYS = new Set([
- 'avatar',
- 'avatarUrl',
- 'avatar_url',
- 'accountAvatar',
- 'authorAvatar',
- 'cover',
- 'coverUrl',
- 'cover_url',
- 'thumbnail',
- 'thumbnailUrl',
- 'thumbnail_url',
- ]);
- function isVolatileRemoteImageUrl(value: string): boolean {
- const trimmed = value.trim();
- if (!trimmed || trimmed.startsWith('data:') || trimmed.startsWith('blob:')) {
- return false;
- }
- try {
- const url = new URL(trimmed);
- const host = url.hostname.toLowerCase();
- const path = url.pathname.toLowerCase();
- if (VOLATILE_IMAGE_HOSTS.has(host) && VOLATILE_IMAGE_PATH_PARTS.some((part) => path.includes(part))) {
- return true;
- }
- return host.endsWith('.video.qq.com') && url.searchParams.has('encfilekey');
- } catch {
- return false;
- }
- }
- export function getSafeImageSrc(value: string | null | undefined): string | undefined {
- if (!value) return undefined;
- const trimmed = value.trim();
- if (!trimmed || isVolatileRemoteImageUrl(trimmed)) return undefined;
- return trimmed;
- }
- export function sanitizeApiImageFields<T>(payload: T): T {
- const seen = new WeakSet<object>();
- function visit(value: unknown): unknown {
- if (!value || typeof value !== 'object') return value;
- if (seen.has(value)) return value;
- seen.add(value);
- if (Array.isArray(value)) {
- value.forEach((item) => visit(item));
- return value;
- }
- const record = value as Record<string, unknown>;
- Object.keys(record).forEach((key) => {
- const fieldValue = record[key];
- if (typeof fieldValue === 'string' && IMAGE_FIELD_KEYS.has(key) && isVolatileRemoteImageUrl(fieldValue)) {
- record[key] = '';
- return;
- }
- visit(fieldValue);
- });
- return value;
- }
- return visit(payload) as T;
- }
|