Fix: Prefer Hugging Face storage in HF Spaces, handle Telegram failures gracefully
Browse files- src/app/api/v1/upload/route.ts +96 -17
- src/app/api/v2/upload/route.ts +78 -29
src/app/api/v1/upload/route.ts
CHANGED
|
@@ -47,17 +47,21 @@ export async function POST(req: NextRequest) {
|
|
| 47 |
// 2. Generate ID first
|
| 48 |
const id = customId ? customId.toLowerCase().replace(/[^a-z0-9-]/g, '-') : generateId();
|
| 49 |
|
| 50 |
-
// Determine storage based on
|
|
|
|
| 51 |
const LARGE_FILE_THRESHOLD = 50 * 1024 * 1024; // 50MB
|
| 52 |
const isLargeFile = file.size > LARGE_FILE_THRESHOLD;
|
| 53 |
const useHFForLargeFiles = isHuggingFaceConfigured() && process.env.USE_HF_FOR_LARGE_FILES === 'true';
|
|
|
|
|
|
|
| 54 |
|
| 55 |
-
// 1. Upload to storage (
|
| 56 |
let storageResult: { file_id: string; file_url?: string };
|
| 57 |
let storageType: 'telegram' | 'huggingface' = 'telegram';
|
| 58 |
|
| 59 |
-
|
| 60 |
-
|
|
|
|
| 61 |
try {
|
| 62 |
const fileName = customId || `upload-${id}`;
|
| 63 |
const hfResult = await uploadToHuggingFace(file, fileName, id);
|
|
@@ -67,32 +71,98 @@ export async function POST(req: NextRequest) {
|
|
| 67 |
};
|
| 68 |
storageType = 'huggingface';
|
| 69 |
|
| 70 |
-
// Also forward to Telegram chat (for backup/notification)
|
| 71 |
try {
|
| 72 |
let mediaType: 'photo' | 'animation' | 'video' = 'photo';
|
| 73 |
if (file.type.startsWith('video/')) mediaType = 'video';
|
| 74 |
if (file.type === 'image/gif') mediaType = 'animation';
|
| 75 |
await uploadToTelegram(file, fileName, `π¦ <b>Uploaded in web (HF Hub)</b>\nπ <b>HF URL:</b> ${hfResult.file_url}`, mediaType);
|
| 76 |
} catch (tgError) {
|
| 77 |
-
console.error('Failed to forward HF upload to Telegram chat:', tgError);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 78 |
// Don't fail the upload if Telegram forwarding fails
|
| 79 |
}
|
| 80 |
} catch (hfError: any) {
|
| 81 |
console.error('HF upload failed, falling back to Telegram:', hfError);
|
| 82 |
-
// Fallback to Telegram
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 83 |
let mediaType: 'photo' | 'animation' | 'video' = 'photo';
|
| 84 |
if (file.type.startsWith('video/')) mediaType = 'video';
|
| 85 |
if (file.type === 'image/gif') mediaType = 'animation';
|
| 86 |
const telegramResult = await uploadToTelegram(file, 'upload', 'π¦ <b>Uploaded in web</b>', mediaType);
|
| 87 |
storageResult = { file_id: telegramResult.file_id };
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 88 |
}
|
| 89 |
-
} else {
|
| 90 |
-
// Use Telegram for small files (<50MB) or if HF not configured
|
| 91 |
-
let mediaType: 'photo' | 'animation' | 'video' = 'photo';
|
| 92 |
-
if (file.type.startsWith('video/')) mediaType = 'video';
|
| 93 |
-
if (file.type === 'image/gif') mediaType = 'animation';
|
| 94 |
-
const telegramResult = await uploadToTelegram(file, 'upload', 'π¦ <b>Uploaded in web</b>', mediaType);
|
| 95 |
-
storageResult = { file_id: telegramResult.file_id };
|
| 96 |
}
|
| 97 |
|
| 98 |
const record: any = {
|
|
@@ -116,8 +186,12 @@ export async function POST(req: NextRequest) {
|
|
| 116 |
|
| 117 |
const publicUrl = `${baseUrl}/i/${id}`;
|
| 118 |
|
| 119 |
-
// Log to Telegram
|
| 120 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 121 |
|
| 122 |
return NextResponse.json({
|
| 123 |
success: true,
|
|
@@ -131,7 +205,12 @@ export async function POST(req: NextRequest) {
|
|
| 131 |
|
| 132 |
} catch (error: any) {
|
| 133 |
console.error('Upload API Error:', error);
|
| 134 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 135 |
return NextResponse.json({
|
| 136 |
success: false,
|
| 137 |
error: { code: 'INTERNAL_ERROR', message: error.message || 'Server processed request failed' }
|
|
|
|
| 47 |
// 2. Generate ID first
|
| 48 |
const id = customId ? customId.toLowerCase().replace(/[^a-z0-9-]/g, '-') : generateId();
|
| 49 |
|
| 50 |
+
// Determine storage based on configuration
|
| 51 |
+
// Prefer Hugging Face if configured (especially in HF Spaces environment)
|
| 52 |
const LARGE_FILE_THRESHOLD = 50 * 1024 * 1024; // 50MB
|
| 53 |
const isLargeFile = file.size > LARGE_FILE_THRESHOLD;
|
| 54 |
const useHFForLargeFiles = isHuggingFaceConfigured() && process.env.USE_HF_FOR_LARGE_FILES === 'true';
|
| 55 |
+
const useHFStorage = isHuggingFaceConfigured() && (process.env.USE_HF_STORAGE === 'true' || process.env.SPACE_ID); // Auto-enable in HF Spaces
|
| 56 |
+
const isHFEnvironment = !!process.env.SPACE_ID; // Detect Hugging Face Spaces environment
|
| 57 |
|
| 58 |
+
// 1. Upload to storage (prefer Hugging Face if configured, especially in HF Spaces)
|
| 59 |
let storageResult: { file_id: string; file_url?: string };
|
| 60 |
let storageType: 'telegram' | 'huggingface' = 'telegram';
|
| 61 |
|
| 62 |
+
// Priority: HF Storage > HF for large files > Telegram (with graceful fallback)
|
| 63 |
+
if (useHFStorage) {
|
| 64 |
+
// Use HF Hub for all files if configured
|
| 65 |
try {
|
| 66 |
const fileName = customId || `upload-${id}`;
|
| 67 |
const hfResult = await uploadToHuggingFace(file, fileName, id);
|
|
|
|
| 71 |
};
|
| 72 |
storageType = 'huggingface';
|
| 73 |
|
| 74 |
+
// Also forward to Telegram chat (for backup/notification) - optional
|
| 75 |
try {
|
| 76 |
let mediaType: 'photo' | 'animation' | 'video' = 'photo';
|
| 77 |
if (file.type.startsWith('video/')) mediaType = 'video';
|
| 78 |
if (file.type === 'image/gif') mediaType = 'animation';
|
| 79 |
await uploadToTelegram(file, fileName, `π¦ <b>Uploaded in web (HF Hub)</b>\nπ <b>HF URL:</b> ${hfResult.file_url}`, mediaType);
|
| 80 |
} catch (tgError) {
|
| 81 |
+
console.error('Failed to forward HF upload to Telegram chat (optional):', tgError);
|
| 82 |
+
// Don't fail the upload if Telegram forwarding fails
|
| 83 |
+
}
|
| 84 |
+
} catch (hfError: any) {
|
| 85 |
+
console.error('HF upload failed:', hfError);
|
| 86 |
+
// In HF Spaces, don't fallback to Telegram (it won't work)
|
| 87 |
+
if (isHFEnvironment) {
|
| 88 |
+
throw new Error(`Hugging Face upload failed: ${hfError.message}. Please check HF_TOKEN and HF_REPO_ID configuration.`);
|
| 89 |
+
}
|
| 90 |
+
// Fallback to Telegram only if not in HF Spaces
|
| 91 |
+
try {
|
| 92 |
+
let mediaType: 'photo' | 'animation' | 'video' = 'photo';
|
| 93 |
+
if (file.type.startsWith('video/')) mediaType = 'video';
|
| 94 |
+
if (file.type === 'image/gif') mediaType = 'animation';
|
| 95 |
+
const telegramResult = await uploadToTelegram(file, 'upload', 'π¦ <b>Uploaded in web</b>', mediaType);
|
| 96 |
+
storageResult = { file_id: telegramResult.file_id };
|
| 97 |
+
} catch (tgError: any) {
|
| 98 |
+
throw new Error(`Both HF and Telegram uploads failed. HF: ${hfError.message}, Telegram: ${tgError.message}`);
|
| 99 |
+
}
|
| 100 |
+
}
|
| 101 |
+
} else if (useHFForLargeFiles && isLargeFile) {
|
| 102 |
+
// Use HF Hub for large files only
|
| 103 |
+
try {
|
| 104 |
+
const fileName = customId || `upload-${id}`;
|
| 105 |
+
const hfResult = await uploadToHuggingFace(file, fileName, id);
|
| 106 |
+
storageResult = {
|
| 107 |
+
file_id: hfResult.file_id,
|
| 108 |
+
file_url: hfResult.file_url
|
| 109 |
+
};
|
| 110 |
+
storageType = 'huggingface';
|
| 111 |
+
|
| 112 |
+
// Also forward to Telegram chat (for backup/notification) - optional
|
| 113 |
+
try {
|
| 114 |
+
let mediaType: 'photo' | 'animation' | 'video' = 'photo';
|
| 115 |
+
if (file.type.startsWith('video/')) mediaType = 'video';
|
| 116 |
+
if (file.type === 'image/gif') mediaType = 'animation';
|
| 117 |
+
await uploadToTelegram(file, fileName, `π¦ <b>Uploaded in web (HF Hub)</b>\nπ <b>HF URL:</b> ${hfResult.file_url}`, mediaType);
|
| 118 |
+
} catch (tgError) {
|
| 119 |
+
console.error('Failed to forward HF upload to Telegram chat (optional):', tgError);
|
| 120 |
// Don't fail the upload if Telegram forwarding fails
|
| 121 |
}
|
| 122 |
} catch (hfError: any) {
|
| 123 |
console.error('HF upload failed, falling back to Telegram:', hfError);
|
| 124 |
+
// Fallback to Telegram if HF fails
|
| 125 |
+
try {
|
| 126 |
+
let mediaType: 'photo' | 'animation' | 'video' = 'photo';
|
| 127 |
+
if (file.type.startsWith('video/')) mediaType = 'video';
|
| 128 |
+
if (file.type === 'image/gif') mediaType = 'animation';
|
| 129 |
+
const telegramResult = await uploadToTelegram(file, 'upload', 'π¦ <b>Uploaded in web</b>', mediaType);
|
| 130 |
+
storageResult = { file_id: telegramResult.file_id };
|
| 131 |
+
} catch (tgError: any) {
|
| 132 |
+
throw new Error(`Upload failed. HF: ${hfError.message}, Telegram: ${tgError.message}`);
|
| 133 |
+
}
|
| 134 |
+
}
|
| 135 |
+
} else {
|
| 136 |
+
// Use Telegram (default) - but check if we're in HF Spaces
|
| 137 |
+
if (isHFEnvironment && !isHuggingFaceConfigured()) {
|
| 138 |
+
throw new Error('Telegram API is not accessible in Hugging Face Spaces. Please configure HF_TOKEN and HF_REPO_ID to use Hugging Face storage.');
|
| 139 |
+
}
|
| 140 |
+
|
| 141 |
+
try {
|
| 142 |
let mediaType: 'photo' | 'animation' | 'video' = 'photo';
|
| 143 |
if (file.type.startsWith('video/')) mediaType = 'video';
|
| 144 |
if (file.type === 'image/gif') mediaType = 'animation';
|
| 145 |
const telegramResult = await uploadToTelegram(file, 'upload', 'π¦ <b>Uploaded in web</b>', mediaType);
|
| 146 |
storageResult = { file_id: telegramResult.file_id };
|
| 147 |
+
} catch (tgError: any) {
|
| 148 |
+
// If Telegram fails and HF is configured, try HF as fallback
|
| 149 |
+
if (isHuggingFaceConfigured()) {
|
| 150 |
+
console.error('Telegram upload failed, trying HF as fallback:', tgError);
|
| 151 |
+
try {
|
| 152 |
+
const fileName = customId || `upload-${id}`;
|
| 153 |
+
const hfResult = await uploadToHuggingFace(file, fileName, id);
|
| 154 |
+
storageResult = {
|
| 155 |
+
file_id: hfResult.file_id,
|
| 156 |
+
file_url: hfResult.file_url
|
| 157 |
+
};
|
| 158 |
+
storageType = 'huggingface';
|
| 159 |
+
} catch (hfError: any) {
|
| 160 |
+
throw new Error(`Both Telegram and HF uploads failed. Telegram: ${tgError.message}, HF: ${hfError.message}`);
|
| 161 |
+
}
|
| 162 |
+
} else {
|
| 163 |
+
throw new Error(`Telegram upload failed: ${tgError.message}. Consider configuring Hugging Face storage.`);
|
| 164 |
+
}
|
| 165 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 166 |
}
|
| 167 |
|
| 168 |
const record: any = {
|
|
|
|
| 186 |
|
| 187 |
const publicUrl = `${baseUrl}/i/${id}`;
|
| 188 |
|
| 189 |
+
// Log to Telegram (optional - don't fail if it doesn't work)
|
| 190 |
+
try {
|
| 191 |
+
await sendLog(`π <b>New Web Upload</b>\n\nType: ${file.type}\nSize: ${(file.size / 1024 / 1024).toFixed(2)} MB\nLink: ${publicUrl}`);
|
| 192 |
+
} catch (logError) {
|
| 193 |
+
console.error('Failed to send log to Telegram (optional):', logError);
|
| 194 |
+
}
|
| 195 |
|
| 196 |
return NextResponse.json({
|
| 197 |
success: true,
|
|
|
|
| 205 |
|
| 206 |
} catch (error: any) {
|
| 207 |
console.error('Upload API Error:', error);
|
| 208 |
+
// Try to log error to Telegram (optional)
|
| 209 |
+
try {
|
| 210 |
+
await sendLog(`β <b>Web Upload Error</b>\n\nError: ${error.message || error}`);
|
| 211 |
+
} catch (logError) {
|
| 212 |
+
console.error('Failed to send error log to Telegram (optional):', logError);
|
| 213 |
+
}
|
| 214 |
return NextResponse.json({
|
| 215 |
success: false,
|
| 216 |
error: { code: 'INTERNAL_ERROR', message: error.message || 'Server processed request failed' }
|
src/app/api/v2/upload/route.ts
CHANGED
|
@@ -73,18 +73,21 @@ export async function POST(req: NextRequest) {
|
|
| 73 |
// 2. Generate ID
|
| 74 |
const id = customId ? customId.toLowerCase().replace(/[^a-z0-9-]/g, '-') : generateId();
|
| 75 |
|
| 76 |
-
// Determine storage based on
|
| 77 |
-
//
|
| 78 |
const LARGE_FILE_THRESHOLD = 50 * 1024 * 1024; // 50MB
|
| 79 |
const isLargeFile = file.size > LARGE_FILE_THRESHOLD;
|
| 80 |
const useHFForLargeFiles = isHuggingFaceConfigured() && process.env.USE_HF_FOR_LARGE_FILES === 'true';
|
|
|
|
|
|
|
| 81 |
|
| 82 |
-
// 1. Upload to storage (Hugging Face
|
| 83 |
let storageResult: { file_id: string; file_url?: string };
|
| 84 |
let storageType: 'telegram' | 'huggingface' = 'telegram';
|
| 85 |
|
| 86 |
-
|
| 87 |
-
|
|
|
|
| 88 |
try {
|
| 89 |
const fileName = customId || `upload-${id}`;
|
| 90 |
const hfResult = await uploadToHuggingFace(file, fileName, id);
|
|
@@ -94,27 +97,35 @@ export async function POST(req: NextRequest) {
|
|
| 94 |
};
|
| 95 |
storageType = 'huggingface';
|
| 96 |
|
| 97 |
-
// Also forward to Telegram chat (for backup/notification)
|
| 98 |
try {
|
| 99 |
let mediaType: 'photo' | 'animation' | 'video' = 'photo';
|
| 100 |
if (file.type.startsWith('video/')) mediaType = 'video';
|
| 101 |
if (file.type === 'image/gif') mediaType = 'animation';
|
| 102 |
await uploadToTelegram(file, fileName, `π¦ <b>Uploaded via API v2 (HF Hub)</b>\nπ <b>HF URL:</b> ${hfResult.file_url}`, mediaType);
|
| 103 |
} catch (tgError) {
|
| 104 |
-
console.error('Failed to forward HF upload to Telegram chat:', tgError);
|
| 105 |
// Don't fail the upload if Telegram forwarding fails
|
| 106 |
}
|
| 107 |
} catch (hfError: any) {
|
| 108 |
-
console.error('HF upload failed
|
| 109 |
-
//
|
| 110 |
-
|
| 111 |
-
|
| 112 |
-
|
| 113 |
-
|
| 114 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 115 |
}
|
| 116 |
-
} else if (
|
| 117 |
-
// Use
|
| 118 |
try {
|
| 119 |
const fileName = customId || `upload-${id}`;
|
| 120 |
const hfResult = await uploadToHuggingFace(file, fileName, id);
|
|
@@ -124,31 +135,60 @@ export async function POST(req: NextRequest) {
|
|
| 124 |
};
|
| 125 |
storageType = 'huggingface';
|
| 126 |
|
| 127 |
-
// Also forward to Telegram chat (for backup/notification)
|
| 128 |
try {
|
| 129 |
let mediaType: 'photo' | 'animation' | 'video' = 'photo';
|
| 130 |
if (file.type.startsWith('video/')) mediaType = 'video';
|
| 131 |
if (file.type === 'image/gif') mediaType = 'animation';
|
| 132 |
await uploadToTelegram(file, fileName, `π¦ <b>Uploaded via API v2 (HF Hub)</b>\nπ <b>HF URL:</b> ${hfResult.file_url}`, mediaType);
|
| 133 |
} catch (tgError) {
|
| 134 |
-
console.error('Failed to forward HF upload to Telegram chat:', tgError);
|
| 135 |
// Don't fail the upload if Telegram forwarding fails
|
| 136 |
}
|
| 137 |
} catch (hfError: any) {
|
| 138 |
console.error('HF upload failed, falling back to Telegram:', hfError);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 139 |
let mediaType: 'photo' | 'animation' | 'video' = 'photo';
|
| 140 |
if (file.type.startsWith('video/')) mediaType = 'video';
|
| 141 |
if (file.type === 'image/gif') mediaType = 'animation';
|
| 142 |
const telegramResult = await uploadToTelegram(file, 'upload', 'π¦ <b>Uploaded via API v2</b>', mediaType);
|
| 143 |
storageResult = { file_id: telegramResult.file_id };
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 144 |
}
|
| 145 |
-
} else {
|
| 146 |
-
// Use Telegram (default)
|
| 147 |
-
let mediaType: 'photo' | 'animation' | 'video' = 'photo';
|
| 148 |
-
if (file.type.startsWith('video/')) mediaType = 'video';
|
| 149 |
-
if (file.type === 'image/gif') mediaType = 'animation';
|
| 150 |
-
const telegramResult = await uploadToTelegram(file, 'upload', 'π¦ <b>Uploaded via API v2</b>', mediaType);
|
| 151 |
-
storageResult = { file_id: telegramResult.file_id };
|
| 152 |
}
|
| 153 |
|
| 154 |
const record: any = {
|
|
@@ -177,9 +217,13 @@ export async function POST(req: NextRequest) {
|
|
| 177 |
|
| 178 |
const publicUrl = `${baseUrl}/i/${id}`;
|
| 179 |
|
| 180 |
-
// Log to Telegram
|
| 181 |
-
|
| 182 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 183 |
|
| 184 |
// Trigger webhooks if user has any
|
| 185 |
if (auth?.userId) {
|
|
@@ -213,7 +257,12 @@ export async function POST(req: NextRequest) {
|
|
| 213 |
|
| 214 |
} catch (error: any) {
|
| 215 |
console.error('Upload API Error:', error);
|
| 216 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 217 |
return NextResponse.json({
|
| 218 |
success: false,
|
| 219 |
error: { code: 'INTERNAL_ERROR', message: error.message || 'Server processed request failed' }
|
|
|
|
| 73 |
// 2. Generate ID
|
| 74 |
const id = customId ? customId.toLowerCase().replace(/[^a-z0-9-]/g, '-') : generateId();
|
| 75 |
|
| 76 |
+
// Determine storage based on configuration
|
| 77 |
+
// Prefer Hugging Face if configured (especially in HF Spaces environment)
|
| 78 |
const LARGE_FILE_THRESHOLD = 50 * 1024 * 1024; // 50MB
|
| 79 |
const isLargeFile = file.size > LARGE_FILE_THRESHOLD;
|
| 80 |
const useHFForLargeFiles = isHuggingFaceConfigured() && process.env.USE_HF_FOR_LARGE_FILES === 'true';
|
| 81 |
+
const useHFStorage = isHuggingFaceConfigured() && (process.env.USE_HF_STORAGE === 'true' || process.env.SPACE_ID); // Auto-enable in HF Spaces
|
| 82 |
+
const isHFEnvironment = !!process.env.SPACE_ID; // Detect Hugging Face Spaces environment
|
| 83 |
|
| 84 |
+
// 1. Upload to storage (prefer Hugging Face if configured, especially in HF Spaces)
|
| 85 |
let storageResult: { file_id: string; file_url?: string };
|
| 86 |
let storageType: 'telegram' | 'huggingface' = 'telegram';
|
| 87 |
|
| 88 |
+
// Priority: HF Storage > HF for large files > Telegram (with graceful fallback)
|
| 89 |
+
if (useHFStorage) {
|
| 90 |
+
// Use HF Hub for all files if configured
|
| 91 |
try {
|
| 92 |
const fileName = customId || `upload-${id}`;
|
| 93 |
const hfResult = await uploadToHuggingFace(file, fileName, id);
|
|
|
|
| 97 |
};
|
| 98 |
storageType = 'huggingface';
|
| 99 |
|
| 100 |
+
// Also forward to Telegram chat (for backup/notification) - optional
|
| 101 |
try {
|
| 102 |
let mediaType: 'photo' | 'animation' | 'video' = 'photo';
|
| 103 |
if (file.type.startsWith('video/')) mediaType = 'video';
|
| 104 |
if (file.type === 'image/gif') mediaType = 'animation';
|
| 105 |
await uploadToTelegram(file, fileName, `π¦ <b>Uploaded via API v2 (HF Hub)</b>\nπ <b>HF URL:</b> ${hfResult.file_url}`, mediaType);
|
| 106 |
} catch (tgError) {
|
| 107 |
+
console.error('Failed to forward HF upload to Telegram chat (optional):', tgError);
|
| 108 |
// Don't fail the upload if Telegram forwarding fails
|
| 109 |
}
|
| 110 |
} catch (hfError: any) {
|
| 111 |
+
console.error('HF upload failed:', hfError);
|
| 112 |
+
// In HF Spaces, don't fallback to Telegram (it won't work)
|
| 113 |
+
if (isHFEnvironment) {
|
| 114 |
+
throw new Error(`Hugging Face upload failed: ${hfError.message}. Please check HF_TOKEN and HF_REPO_ID configuration.`);
|
| 115 |
+
}
|
| 116 |
+
// Fallback to Telegram only if not in HF Spaces
|
| 117 |
+
try {
|
| 118 |
+
let mediaType: 'photo' | 'animation' | 'video' = 'photo';
|
| 119 |
+
if (file.type.startsWith('video/')) mediaType = 'video';
|
| 120 |
+
if (file.type === 'image/gif') mediaType = 'animation';
|
| 121 |
+
const telegramResult = await uploadToTelegram(file, 'upload', 'π¦ <b>Uploaded via API v2</b>', mediaType);
|
| 122 |
+
storageResult = { file_id: telegramResult.file_id };
|
| 123 |
+
} catch (tgError: any) {
|
| 124 |
+
throw new Error(`Both HF and Telegram uploads failed. HF: ${hfError.message}, Telegram: ${tgError.message}`);
|
| 125 |
+
}
|
| 126 |
}
|
| 127 |
+
} else if (useHFForLargeFiles && isLargeFile) {
|
| 128 |
+
// Use Hugging Face Hub for large files only
|
| 129 |
try {
|
| 130 |
const fileName = customId || `upload-${id}`;
|
| 131 |
const hfResult = await uploadToHuggingFace(file, fileName, id);
|
|
|
|
| 135 |
};
|
| 136 |
storageType = 'huggingface';
|
| 137 |
|
| 138 |
+
// Also forward to Telegram chat (for backup/notification) - optional
|
| 139 |
try {
|
| 140 |
let mediaType: 'photo' | 'animation' | 'video' = 'photo';
|
| 141 |
if (file.type.startsWith('video/')) mediaType = 'video';
|
| 142 |
if (file.type === 'image/gif') mediaType = 'animation';
|
| 143 |
await uploadToTelegram(file, fileName, `π¦ <b>Uploaded via API v2 (HF Hub)</b>\nπ <b>HF URL:</b> ${hfResult.file_url}`, mediaType);
|
| 144 |
} catch (tgError) {
|
| 145 |
+
console.error('Failed to forward HF upload to Telegram chat (optional):', tgError);
|
| 146 |
// Don't fail the upload if Telegram forwarding fails
|
| 147 |
}
|
| 148 |
} catch (hfError: any) {
|
| 149 |
console.error('HF upload failed, falling back to Telegram:', hfError);
|
| 150 |
+
// Fallback to Telegram if HF fails
|
| 151 |
+
try {
|
| 152 |
+
let mediaType: 'photo' | 'animation' | 'video' = 'photo';
|
| 153 |
+
if (file.type.startsWith('video/')) mediaType = 'video';
|
| 154 |
+
if (file.type === 'image/gif') mediaType = 'animation';
|
| 155 |
+
const telegramResult = await uploadToTelegram(file, 'upload', 'π¦ <b>Uploaded via API v2</b>', mediaType);
|
| 156 |
+
storageResult = { file_id: telegramResult.file_id };
|
| 157 |
+
} catch (tgError: any) {
|
| 158 |
+
throw new Error(`Upload failed. HF: ${hfError.message}, Telegram: ${tgError.message}`);
|
| 159 |
+
}
|
| 160 |
+
}
|
| 161 |
+
} else {
|
| 162 |
+
// Use Telegram (default) - but check if we're in HF Spaces
|
| 163 |
+
if (isHFEnvironment && !isHuggingFaceConfigured()) {
|
| 164 |
+
throw new Error('Telegram API is not accessible in Hugging Face Spaces. Please configure HF_TOKEN and HF_REPO_ID to use Hugging Face storage.');
|
| 165 |
+
}
|
| 166 |
+
|
| 167 |
+
try {
|
| 168 |
let mediaType: 'photo' | 'animation' | 'video' = 'photo';
|
| 169 |
if (file.type.startsWith('video/')) mediaType = 'video';
|
| 170 |
if (file.type === 'image/gif') mediaType = 'animation';
|
| 171 |
const telegramResult = await uploadToTelegram(file, 'upload', 'π¦ <b>Uploaded via API v2</b>', mediaType);
|
| 172 |
storageResult = { file_id: telegramResult.file_id };
|
| 173 |
+
} catch (tgError: any) {
|
| 174 |
+
// If Telegram fails and HF is configured, try HF as fallback
|
| 175 |
+
if (isHuggingFaceConfigured()) {
|
| 176 |
+
console.error('Telegram upload failed, trying HF as fallback:', tgError);
|
| 177 |
+
try {
|
| 178 |
+
const fileName = customId || `upload-${id}`;
|
| 179 |
+
const hfResult = await uploadToHuggingFace(file, fileName, id);
|
| 180 |
+
storageResult = {
|
| 181 |
+
file_id: hfResult.file_id,
|
| 182 |
+
file_url: hfResult.file_url
|
| 183 |
+
};
|
| 184 |
+
storageType = 'huggingface';
|
| 185 |
+
} catch (hfError: any) {
|
| 186 |
+
throw new Error(`Both Telegram and HF uploads failed. Telegram: ${tgError.message}, HF: ${hfError.message}`);
|
| 187 |
+
}
|
| 188 |
+
} else {
|
| 189 |
+
throw new Error(`Telegram upload failed: ${tgError.message}. Consider configuring Hugging Face storage.`);
|
| 190 |
+
}
|
| 191 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 192 |
}
|
| 193 |
|
| 194 |
const record: any = {
|
|
|
|
| 217 |
|
| 218 |
const publicUrl = `${baseUrl}/i/${id}`;
|
| 219 |
|
| 220 |
+
// Log to Telegram (optional - don't fail if it doesn't work)
|
| 221 |
+
try {
|
| 222 |
+
const authInfo = auth?.apiKey ? `API Key: ${auth.apiKey.prefix}...` : auth?.userId ? `User: ${auth.userId}` : 'Anonymous';
|
| 223 |
+
await sendLog(`π <b>New API v2 Upload</b>\n\n${authInfo}\nType: ${file.type}\nSize: ${(file.size / 1024 / 1024).toFixed(2)} MB\nLink: ${publicUrl}`);
|
| 224 |
+
} catch (logError) {
|
| 225 |
+
console.error('Failed to send log to Telegram (optional):', logError);
|
| 226 |
+
}
|
| 227 |
|
| 228 |
// Trigger webhooks if user has any
|
| 229 |
if (auth?.userId) {
|
|
|
|
| 257 |
|
| 258 |
} catch (error: any) {
|
| 259 |
console.error('Upload API Error:', error);
|
| 260 |
+
// Try to log error to Telegram (optional)
|
| 261 |
+
try {
|
| 262 |
+
await sendLog(`β <b>API v2 Upload Error</b>\n\nError: ${error.message || error}`);
|
| 263 |
+
} catch (logError) {
|
| 264 |
+
console.error('Failed to send error log to Telegram (optional):', logError);
|
| 265 |
+
}
|
| 266 |
return NextResponse.json({
|
| 267 |
success: false,
|
| 268 |
error: { code: 'INTERNAL_ERROR', message: error.message || 'Server processed request failed' }
|