2026-04-10 11:24:28 +02:00
const DROPBOX_APP_KEY = process . env . DROPBOX_APP_KEY ;
const DROPBOX_APP_SECRET = process . env . DROPBOX_APP_SECRET ;
const DROPBOX_REFRESH_TOKEN = process . env . DROPBOX_REFRESH_TOKEN ;
async function getAccessToken () {
const response = await fetch ( 'https://api.dropboxapi.com/oauth2/token' , {
method : 'POST' ,
headers : { 'Content-Type' : 'application/x-www-form-urlencoded' },
body : new URLSearchParams ({
grant_type : 'refresh_token' ,
refresh_token : DROPBOX_REFRESH_TOKEN ,
client_id : DROPBOX_APP_KEY ,
client_secret : DROPBOX_APP_SECRET ,
})
});
const data = await response . json ();
if ( ! data . access_token ) {
throw new Error ( 'Failed to get access token: ' + JSON . stringify ( data ));
}
return data . access_token ;
}
2026-04-10 10:54:50 +02:00
2026-03-27 13:26:16 +01:00
export default async function handler ( req , res ) {
2026-04-10 11:24:28 +02:00
let accessToken ;
try {
accessToken = await getAccessToken ();
} catch ( err ) {
2026-04-22 16:09:00 +02:00
console . warn ( 'Token refresh optional failure (sharing link might still work):' , err . message );
2026-04-10 11:20:16 +02:00
}
2026-04-10 10:54:50 +02:00
if ( req . method === 'GET' && req . query . info === '1' ) {
try {
2026-04-21 08:40:54 +02:00
// In this mode, we'll just return a placeholder rev since we're using a sharing link now
// This satisfies the frontend check without needing a specific API path
2026-04-10 19:56:42 +02:00
res . setHeader ( 'Cache-Control' , 'no-store, no-cache, must-revalidate, proxy-revalidate' );
res . setHeader ( 'Pragma' , 'no-cache' );
res . setHeader ( 'Expires' , '0' );
2026-04-21 08:40:54 +02:00
return res . json ({ rev : 'new-url-v1' , size : 0 , server_modified : new Date (). toISOString () });
2026-04-10 10:54:50 +02:00
} catch ( err ) {
return res . status ( 500 ). json ({ error : err . message });
}
}
2026-03-27 13:26:16 +01:00
try {
2026-04-22 16:17:07 +02:00
const sharingUrl = 'https://www.dropbox.com/scl/fi/8qbl7uoigtfu5x1nn8wvm/Data-Matrix.xlsx?rlkey=s6rkwa2bjrx9gh442gw6w40uk&dl=1' ;
2026-04-21 08:40:54 +02:00
const upstream = await fetch ( sharingUrl , {
method : 'GET' ,
2026-04-10 11:01:55 +02:00
headers : {
2026-04-22 16:17:07 +02:00
'Cache-Control' : 'no-cache' ,
'User-Agent' : 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36'
2026-04-10 11:01:55 +02:00
}
});
2026-04-10 11:20:16 +02:00
2026-04-22 16:17:07 +02:00
const contentType = upstream . headers . get ( 'content-type' );
if ( contentType && contentType . includes ( 'text/html' )) {
console . error ( 'Dropbox returned HTML instead of file' );
return res . status ( 500 ). send ( 'Error: El enlace de Dropbox ha devuelto una página HTML en lugar del archivo. Es probable que el enlace haya caducado o necesite ser renovado.' );
}
2026-04-10 11:20:16 +02:00
if ( ! upstream . ok ) {
const errText = await upstream . text ();
2026-04-21 08:40:54 +02:00
console . error ( 'Dropbox URL error:' , upstream . status , errText );
2026-04-10 11:20:16 +02:00
return res . status ( upstream . status ). send ( 'Dropbox error: ' + errText );
}
2026-04-10 11:01:55 +02:00
const buffer = await upstream . arrayBuffer ();
2026-03-27 13:26:16 +01:00
res . setHeader ( 'Content-Type' , 'application/octet-stream' );
res . setHeader ( 'Cache-Control' , 'no-store' );
2026-04-10 11:01:55 +02:00
res . send ( Buffer . from ( buffer ));
2026-03-27 13:26:16 +01:00
} catch ( err ) {
2026-04-10 11:20:16 +02:00
console . error ( 'Dropbox proxy error:' , err );
2026-03-27 13:26:16 +01:00
res . status ( 500 ). send ( 'Proxy error: ' + err . message );
}
}