upload page

This commit is contained in:
Robin Appelman 2023-04-09 19:03:05 +02:00
commit a8f0d8e299
8 changed files with 171 additions and 18 deletions

40
script/header.js Normal file
View file

@ -0,0 +1,40 @@
DataView.prototype.getString = function(offset, length){
let end = typeof length == 'number' ? offset + length : this.byteLength;
let text = '';
let val = -1;
while (offset < this.byteLength && offset < end){
val = this.getUint8(offset++);
if (val === 0) break;
text += String.fromCharCode(val);
}
return text;
};
export async function parseHeader(file, cb) {
const data = await readFile(file);
const view = new DataView(data);
return {
'type': view.getString(0, 8),
'server': view.getString(16, 260),
'nick': view.getString(276, 260),
'map': view.getString(536, 260),
'game': view.getString(796, 260),
'duration': view.getFloat32(1056, true),
'ticks': view.getUint32(1060, true),
};
}
async function readFile(file) {
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.onload = function () {
resolve(reader.result)
};
reader.onerror = reject;
reader.readAsArrayBuffer(file);
});
}

7
script/ready.js Normal file
View file

@ -0,0 +1,7 @@
export function ready(cb) {
if (document.readyState === "complete") {
cb();
} else {
document.addEventListener("DOMContentLoaded", cb);
}
}

View file

@ -1,3 +0,0 @@
export function test() {
console.log("import test");
}

18
script/time.js Normal file
View file

@ -0,0 +1,18 @@
export function formatDuration(input) {
if (!input) {
return '0:00';
}
const hours = Math.floor(input / 3600);
const minutes = Math.floor((input - (hours * 3600)) / 60);
const seconds = Math.floor(input - (hours * 3600) - (minutes * 60));
const hourString = (hours < 10) ? "0" + hours : "" + hours;
const minuteString = (minutes < 10) ? "0" + minutes : "" + minutes;
const secondString = (seconds < 10) ? "0" + seconds : "" + seconds;
if (hourString !== '00') {
return hourString + ':' + minuteString + ':' + secondString;
} else {
return minuteString + ':' + secondString;
}
}

View file

@ -1,6 +1,72 @@
import {test} from './test';
import {ready} from './ready';
import {parseHeader} from './header';
import {formatDuration} from './time';
document.addEventListener("DOMContentLoaded", test);
if (document.readyState === "complete") {
test();
ready(() => {
const red_name = document.querySelector(".red input");
const blue_name = document.querySelector(".blue input");
const file = document.querySelector(`.dropzone input[type="file"]`);
const drop_text = document.querySelector(`.dropzone .text`);
const button = document.querySelector(`.upload > button`);
const map = document.querySelector(`.demo-info .map`);
const time = document.querySelector(`.demo-info .time`);
const apiBase = document.querySelector(`input[name="api"]`).value;
const key = document.querySelector(`.key`).textContent;
let selectedFile = null;
console.log(key);
file.addEventListener("change", async (event) => {
let file = event.target.files[0];
drop_text.textContent = file.name;
const header = await parseHeader(file)
if (header.type === "HL2DEMO" && header.game === "tf") {
map.textContent = header.map;
time.textContent = formatDuration(header.duration);
button.removeAttribute("disabled")
selectedFile = file;
} else {
drop_text.textContent = "Malformed demo or not a TF2 demo";
map.textContent = "";
time.textContent = "";
button.setAttribute("disabled", "disabled");
selectedFile = null;
}
});
button.addEventListener("click", async () => {
button.setAttribute("disabled", "disabled");
if (!selectedFile) {
return;
}
drop_text.textContent = "Uploading...";
try {
window.location.href = await uploadDemo(apiBase, key, red_name.value || 'RED', blue_name.value || 'BLU', selectedFile.name, selectedFile);
} catch (e) {
drop_text.textContent = `Error ${e.message}`;
}
});
})
async function uploadDemo(apiBase, key, red, blue, name, demo) {
const data = new FormData();
data.append('key', key);
data.append('red', red);
data.append('blu', blue);
data.append('name', name);
data.append('demo', demo, demo.name);
const response = await fetch(apiBase + "upload", {
method: 'POST',
body: data
});
if (response.status >= 400) {
throw new Error(await response.text());
}
const body = await response.text();
const matches = body.match(/STV available at: https?:\/\/[^/]+\/(\d+)/);
if (matches) {
return matches[1];
} else {
throw new Error(body);
}
}