mirror of
https://github.com/JonasunderscoreJones/fileshare.jonasjones.dev.git
synced 2025-10-22 23:19:18 +02:00
added analytics tracking
This commit is contained in:
parent
162863b80a
commit
c1c5b81c04
1 changed files with 130 additions and 26 deletions
156
src/index.js
156
src/index.js
|
@ -1,7 +1,7 @@
|
|||
import { nanoid } from "nanoid";
|
||||
|
||||
addEventListener("fetch", event => {
|
||||
event.respondWith(handleRequest(event.request));
|
||||
event.respondWith(handleRequest(event));
|
||||
});
|
||||
|
||||
const headersCORS = {
|
||||
|
@ -10,7 +10,36 @@ const headersCORS = {
|
|||
'Access-Control-Allow-Headers': 'Content-Type, x-Custom-Auth-Key',
|
||||
};
|
||||
|
||||
async function handleRequest(request) {
|
||||
async function recordRequest(request) {
|
||||
|
||||
const analyticsData = {
|
||||
timestamp: Date.now(),
|
||||
domain: new URL(request.url).hostname,
|
||||
method: request.method,
|
||||
path: new URL(request.url).pathname,
|
||||
ipcountry: request.cf.country,
|
||||
}
|
||||
const ANALYTICS_URL = 'https://analytics.jonasjones.dev/requests/record';
|
||||
|
||||
const response = await fetch(ANALYTICS_URL, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'Authorization': ANALYTICS_API_KEY,
|
||||
},
|
||||
body: JSON.stringify(analyticsData)
|
||||
});
|
||||
|
||||
if (response.ok) {
|
||||
console.log('Request recorded successfully');
|
||||
} else {
|
||||
console.error('Failed to record request:', response.status, await response.text());
|
||||
}
|
||||
}
|
||||
|
||||
async function handleRequest(event) {
|
||||
const request = event.request;
|
||||
event.waitUntil(recordRequest(request));
|
||||
const url = new URL(request.url);
|
||||
const { pathname } = url;
|
||||
|
||||
|
@ -28,6 +57,10 @@ async function handleRequest(request) {
|
|||
return handleUpload(request);
|
||||
}
|
||||
|
||||
if (request.method === 'POST' && pathname === '/upload-url') {
|
||||
return handleUrlUpload(request);
|
||||
}
|
||||
|
||||
if (request.method === 'GET' && pathname.startsWith('/download/')) {
|
||||
const filename = pathname.replace('/download/', '');
|
||||
return handleDownload(filename);
|
||||
|
@ -44,11 +77,59 @@ async function handleRequest(request) {
|
|||
|
||||
if (request.method === 'GET' && pathname === '/') {
|
||||
return new Response(htmlForm, {
|
||||
headers: { 'content-type': 'text/html;charset=UTF-8' , ...headersCORS},
|
||||
headers: { 'content-type': 'text/html;charset=UTF-8', ...headersCORS },
|
||||
});
|
||||
}
|
||||
|
||||
return new Response('Not Found', { status: 404 }, headersCORS);
|
||||
return new Response('Not Found', { status: 404, headers: headersCORS });
|
||||
}
|
||||
|
||||
async function handleUrlUpload(request) {
|
||||
const { url, authKey } = await request.json();
|
||||
if (!url || !authKey) {
|
||||
return new Response('Bad Request', { status: 400, headers: headersCORS });
|
||||
}
|
||||
|
||||
if (authKey !== `Bearer ${AUTH_KEY_SECRET}`) {
|
||||
return new Response('Unauthorized', { status: 401, headers: headersCORS });
|
||||
}
|
||||
|
||||
try {
|
||||
const fileResponse = await fetch(url);
|
||||
if (!fileResponse.ok) {
|
||||
throw new Error('Failed to fetch the file');
|
||||
}
|
||||
|
||||
const fileBlob = await fileResponse.blob();
|
||||
const hash = nanoid();
|
||||
const contentType = fileResponse.headers.get('Content-Type') || 'application/octet-stream';
|
||||
const originalName = url.split('/').pop();
|
||||
const deletionTimestamp = Date.now() + 24 * 60 * 60 * 1000; // 24 hours
|
||||
|
||||
await CDN_BUCKET.put(`tempupload/content/${hash}`, fileBlob.stream(), {
|
||||
httpMetadata: { contentType },
|
||||
});
|
||||
|
||||
const indexData = await CDN_BUCKET.get('tempupload/index.json');
|
||||
const index = indexData ? await indexData.json() : [];
|
||||
|
||||
index.push({
|
||||
hash,
|
||||
contentType,
|
||||
originalName,
|
||||
deletionTimestamp,
|
||||
});
|
||||
|
||||
await CDN_BUCKET.put('tempupload/index.json', JSON.stringify(index), {
|
||||
httpMetadata: { contentType: 'application/json' },
|
||||
});
|
||||
|
||||
return new Response(JSON.stringify({ downloadLink: `https://fileshare.jonasjones.dev/download/${hash}` }), {
|
||||
headers: { 'Content-Type': 'application/json', ...headersCORS },
|
||||
});
|
||||
} catch (error) {
|
||||
return new Response(`Error: ${error.message}`, { status: 500, headers: headersCORS });
|
||||
}
|
||||
}
|
||||
|
||||
async function cleanUpExpiredFiles() {
|
||||
|
@ -77,17 +158,15 @@ async function cleanUpExpiredFiles() {
|
|||
}
|
||||
|
||||
async function handleUpload(request) {
|
||||
|
||||
// Password protection
|
||||
const password = request.headers.get('X-Custom-Auth-Key');
|
||||
if (password !== `Bearer ${AUTH_KEY_SECRET}`) {
|
||||
return new Response('Unauthorized', { status: 401 }, headersCORS);
|
||||
return new Response('Unauthorized', { status: 401, headers: headersCORS });
|
||||
}
|
||||
|
||||
const formData = await request.formData();
|
||||
const file = formData.get('file');
|
||||
if (!file) {
|
||||
return new Response('Bad Request', { status: 400 }, headersCORS);
|
||||
return new Response('Bad Request', { status: 400, headers: headersCORS });
|
||||
}
|
||||
|
||||
const hash = nanoid();
|
||||
|
@ -121,18 +200,18 @@ async function handleUpload(request) {
|
|||
async function handleDownload(hash) {
|
||||
const indexData = await CDN_BUCKET.get('tempupload/index.json');
|
||||
if (!indexData) {
|
||||
return new Response('Not Found', { status: 404 }, headersCORS);
|
||||
return new Response('Not Found', { status: 404, headers: headersCORS });
|
||||
}
|
||||
|
||||
const index = await indexData.json();
|
||||
const fileRecord = index.find(file => file.hash === hash);
|
||||
if (!fileRecord) {
|
||||
return new Response('Not Found', { status: 404 }, headersCORS);
|
||||
return new Response('Not Found', { status: 404, headers: headersCORS });
|
||||
}
|
||||
|
||||
const file = await CDN_BUCKET.get(`tempupload/content/${hash}`);
|
||||
if (!file) {
|
||||
return new Response('Not Found', { status: 404 }, headersCORS);
|
||||
return new Response('Not Found', { status: 404, headers: headersCORS });
|
||||
}
|
||||
|
||||
const response = new Response(file.body, {
|
||||
|
@ -147,32 +226,23 @@ async function handleDownload(hash) {
|
|||
}
|
||||
|
||||
async function handleDelete(request) {
|
||||
|
||||
// get pathname
|
||||
const url = new URL(request.url);
|
||||
|
||||
const filehash = url.pathname.replace('/delete/', '');
|
||||
|
||||
console.log('filename', filehash)
|
||||
|
||||
// Password protection
|
||||
const password = request.headers.get('X-Custom-Auth-Key');
|
||||
if (password !== `Bearer ${AUTH_KEY_SECRET}`) {
|
||||
return new Response('Unauthorized', { status: 401 }, headersCORS);
|
||||
return new Response('Unauthorized', { status: 401, headers: headersCORS });
|
||||
}
|
||||
|
||||
const indexData = await CDN_BUCKET.get('tempupload/index.json');
|
||||
if (await !indexData) {
|
||||
console.log('indexData', indexData)
|
||||
return new Response('Not Found', { status: 404 }, headersCORS);
|
||||
return new Response('Not Found', { status: 404, headers: headersCORS });
|
||||
}
|
||||
|
||||
let index = await indexData.json();
|
||||
const fileRecord = index.find(file => file.hash === filehash);
|
||||
if (!fileRecord) {
|
||||
console.log('indexData', indexData)
|
||||
console.log('fileRecord', fileRecord)
|
||||
return new Response('Not Found', { status: 404 }, headersCORS);
|
||||
return new Response('Not Found', { status: 404, headers: headersCORS });
|
||||
}
|
||||
|
||||
await CDN_BUCKET.delete(`tempupload/content/${fileRecord.hash}`);
|
||||
|
@ -182,10 +252,9 @@ async function handleDelete(request) {
|
|||
httpMetadata: { contentType: 'application/json' },
|
||||
});
|
||||
|
||||
return new Response('File deleted', { status: 200 }, headersCORS);
|
||||
return new Response('File deleted', { status: 200, headers: headersCORS });
|
||||
}
|
||||
|
||||
|
||||
const htmlForm = `
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
@ -224,6 +293,14 @@ const htmlForm = `
|
|||
</form>
|
||||
<div id="uploadResponse"></div>
|
||||
|
||||
<h1>Upload from URL</h1>
|
||||
<form id="urlUploadForm">
|
||||
<input type="url" id="fileUrl" placeholder="Enter file URL" required>
|
||||
<input type="password" id="urlAuthKey" placeholder="Enter password" required>
|
||||
<button type="submit">Upload</button>
|
||||
</form>
|
||||
<div id="urlUploadResponse"></div>
|
||||
|
||||
<h1>Delete a File</h1>
|
||||
<form id="deleteForm">
|
||||
<select id="fileSelect" required>
|
||||
|
@ -276,6 +353,33 @@ const htmlForm = `
|
|||
}
|
||||
});
|
||||
|
||||
document.getElementById('urlUploadForm').addEventListener('submit', async (e) => {
|
||||
e.preventDefault();
|
||||
|
||||
const fileUrl = document.getElementById('fileUrl').value;
|
||||
const authKey = document.getElementById('urlAuthKey').value;
|
||||
const responseElement = document.getElementById('urlUploadResponse');
|
||||
responseElement.textContent = 'Downloading and uploading...';
|
||||
|
||||
try {
|
||||
const response = await fetch('https://fileshare.jonasjones.dev/upload-url', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'X-Custom-Auth-Key': \`Bearer \${authKey}\`,
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify({ url: fileUrl, authKey: \`Bearer \${authKey}\` })
|
||||
});
|
||||
|
||||
const result = await response.json();
|
||||
responseElement.textContent = \`Download Link: \${result.downloadLink}\`;
|
||||
fetchFileList();
|
||||
fetchFileTable();
|
||||
} catch (error) {
|
||||
responseElement.textContent = \`Error: \${error.message}\`;
|
||||
}
|
||||
});
|
||||
|
||||
document.getElementById('deleteForm').addEventListener('submit', async (e) => {
|
||||
e.preventDefault();
|
||||
|
||||
|
@ -333,7 +437,7 @@ const htmlForm = `
|
|||
row.innerHTML = \`
|
||||
<td>\${file.originalName}</td>
|
||||
<td>\${deletionDate}</td>
|
||||
<td><a href="https://fileshare.jonasjones.dev/download/\${file.hash}" >\${file.hash}</a></td>
|
||||
<td><a href="https://fileshare.jonasjones.dev/download/\${file.hash}">\${file.hash}</a></td>
|
||||
\`;
|
||||
fileTableBody.appendChild(row);
|
||||
});
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue