seria/public/assets/seria.js

157 lines
5.6 KiB
JavaScript

const xhr = (function() {
const send = function(method, url, options, body) {
options ??= {};
const xhr = new XMLHttpRequest;
const requestHeadersRaw = options?.headers ?? {};
const requestHeaders = new Map;
if(typeof requestHeadersRaw === 'object')
for(const name in requestHeadersRaw)
if(requestHeadersRaw.hasOwnProperty(name))
requestHeaders.set(name.toLowerCase(), requestHeadersRaw[name]);
if(typeof options.download === 'function') {
xhr.onloadstart = ev => options.download(ev);
xhr.onprogress = ev => options.download(ev);
xhr.onloadend = ev => options.download(ev);
}
if(typeof options.upload === 'function') {
xhr.upload.onloadstart = ev => options.upload(ev);
xhr.upload.onprogress = ev => options.upload(ev);
xhr.upload.onloadend = ev => options.upload(ev);
}
if(options.authed)
xhr.withCredentials = true;
if(typeof options.timeout === 'number')
xhr.timeout = options.timeout;
if(typeof options.abort === 'function')
options.abort(() => xhr.abort());
if(typeof options.xhr === 'function')
options.xhr(() => xhr);
if(typeof body === 'object') {
if(body instanceof URLSearchParams) {
requestHeaders.set('content-type', 'application/x-www-form-urlencoded');
} else if(body instanceof FormData) {
requestHeaders.set('content-type', 'multipart/form-data');
} else if(body instanceof Blob || body instanceof ArrayBuffer || body instanceof DataView) {
if(!requestHeaders.has('content-type'))
requestHeaders.set('content-type', 'application/octet-stream');
} else if(!requestHeaders.has('content-type')) {
const bodyParts = [];
for(const name in body)
if(body.hasOwnProperty(name))
bodyParts.push(encodeURIComponent(name) + '=' + encodeURIComponent(body[name]));
body = bodyParts.join('&');
requestHeaders.set('content-type', 'application/x-www-form-urlencoded');
}
}
return new Promise((resolve, reject) => {
let responseHeaders = undefined;
xhr.onload = ev => resolve({
status: xhr.status,
body: () => xhr.responseText,
json: () => JSON.parse(xhr.responseText),
headers: () => {
if(responseHeaders !== undefined)
return responseHeaders;
responseHeaders = new Map;
const raw = xhr.getAllResponseHeaders().trim().split(/[\r\n]+/);
for(const name in raw)
if(raw.hasOwnProperty(name)) {
const parts = raw[name].split(': ');
responseHeaders.set(parts.shift(), parts.join(': '));
}
return responseHeaders;
},
xhr: xhr,
ev: ev,
});
xhr.onerror = ev => reject({
xhr: xhr,
ev: ev,
});
xhr.open(method, url);
for(const [name, value] of requestHeaders)
xhr.setRequestHeader(name, value);
xhr.send(body);
});
};
return {
send: send,
get: (url, options, body) => send('GET', url, options, body),
post: (url, options, body) => send('POST', url, options, body),
delete: (url, options, body) => send('DELETE', url, options, body),
patch: (url, options, body) => send('PATCH', url, options, body),
put: (url, options, body) => send('PUT', url, options, body),
};
})();
const seria = (function() {
const csrfp = () => document.querySelector('meta[name="csrfp-token"]')?.content ?? '';
const dls = (function() {
return {
rehash: async dlId => {
const result = await xhr.post(`/info/${dlId}/rehash`, { authed: true }, { _csrfp: csrfp() });
if(result.status !== 200) {
if(result.status === 400)
return 'req';
if(result.status === 401)
return 'auth';
if(result.status === 403)
return 'priv';
return 'unk';
}
return result.json();
},
approve: async dlId => {
const result = await xhr.post(`/info/${dlId}/approve`, { authed: true }, { _csrfp: csrfp() });
if(result.status === 204)
return '';
if(result.status === 400)
return 'req';
if(result.status === 401)
return 'auth';
if(result.status === 403)
return 'priv';
return 'unk';
},
deny: async dlId => {
const result = await xhr.post(`/info/${dlId}/deny`, { authed: true }, { _csrfp: csrfp() });
if(result.status === 204)
return '';
if(result.status === 400)
return 'req';
if(result.status === 401)
return 'auth';
if(result.status === 403)
return 'priv';
return 'unk';
},
};
})();
return {
csrfp: csrfp,
dls: dls,
};
})();