const Authentication = require('./authentication') const lang = require('./lang') function safeParseReponse(str, status, url) { if (status === 0) { return new Error(lang.api_down) } if (str.slice(0, 9) === '= 300) { if (out.message) { throw out } console.error('Got error ' + xhr.status + ' but no error message:', out) throw new Error('Unknown or empty response from server.') } if (pagination) { let headers = {} xhr.getAllResponseHeaders().split('\r\n').forEach(function(item) { let splitted = item.split(': ') headers[splitted[0]] = splitted[1] }) out = { headers: headers || {}, data: out, } } return out } return m.request(options) .then(function(res) { clearLoading(request) return res }) .catch(function (error) { clearLoading(request) window.requestAnimationFrame(m.redraw.bind(m)) if (error.status === 403) { Authentication.clearToken() m.route.set('/', { redirect: m.route.get() }) } if (error.response && error.response.status) { return Promise.reject(error.response) } return Promise.reject(error) }) }, uploadBanner: function(bannerFile, token, reporter) { let request = requestIndex++ requests.add(request) api.loading = true var report = reporter || function() {} var data = new FormData() data.append('file', bannerFile) /*data.append('preview', JSON.stringify({ "out": "base64", "format": "avif", "resize": { "width": 360, "height": 203, "fit": "cover", "withoutEnlargement": true, "kernel": "mitchell" }, "avif": { "quality": 40, "effort": 9 } }))*/ data.append('medium', JSON.stringify({ "format": "avif", "resize": { "width": 1280, "height": 720, "fit": "cover", "withoutEnlargement": true, "kernel": "mitchell" }, "avif": { "quality": 75, "effort": 3 } })) report(lang.api_banner_upload) return api.sendRequest({ method: 'POST', url: token.resize + '?token=' + token.token, body: data, }) .then(async (banner) => { let preview = null let quality = 60 while (!preview && quality > 10) { report(lang.format(lang.api_banner_generate, quality)) let check = await api.sendRequest({ method: 'POST', url: token.resize + '/' + banner.filename + '?token=' + token.token, body: { "preview": { "out": "base64", "format": "avif", "resize": { "width": 360, "height": 203, "fit": "cover", "withoutEnlargement": true, "kernel": "mitchell" }, "avif": { "quality": quality, "effort": 9 } }, }, }) if (check.preview.base64.length < 8000) { preview = check.preview.base64 } else { quality -= 5 } } report(null) api.sendRequest({ method: 'DELETE', url: token.delete + banner.filename + '?token=' + token.token, }).catch(err => console.error(err)) return { file: bannerFile, size: bannerFile.size, medium: { filename: banner.medium.filename, path: banner.medium.path, }, preview: { base64: preview, }, } }) .then( function(res) { clearLoading(request) return res }, function(err) { clearLoading(request) return Promise.reject(err) } ) }, prettyFormatBytes: function(bytes) { if (bytes < 1024) { return `${bytes} B` } if (bytes < 1024 * 1024) { return `${(bytes / 1024).toFixed(1)} KB` } if (bytes < 1024 * 1024 * 1024) { return `${(bytes / 1024 / 1024).toFixed(1)} MB` } }, uploadFileProgress: function(options, file, reporter) { let request = requestIndex++ requests.add(request) api.loading = true return new Promise(function(res, rej) { let report = reporter || function() {} let formdata = new FormData() formdata.append('file', file) let request = new XMLHttpRequest() let finished = false let lastMarker = new Date() let lastMarkerLoaded = 0 let lastMarkerSpeed = '...' request.abortRequest = function() { finished = true request.abort() } request.upload.addEventListener('progress', function (e) { let check = new Date() if (check - lastMarker >= 1000) { let loaded = e.loaded - lastMarkerLoaded lastMarkerSpeed = api.prettyFormatBytes(loaded / ((check - lastMarker) / 1000)) lastMarker = check lastMarkerLoaded = e.loaded } report(request, Math.min(e.loaded / file.size * 100, 100), lastMarkerSpeed) }) request.addEventListener('abort', function(e) { finished = true window.requestAnimationFrame(m.redraw.bind(m)) rej() }) request.addEventListener('readystatechange', function(e) { if (finished) return if (request.readyState !== 4) return finished = true let out = safeParseReponse(request.responseText, request.status, options.url) if (out instanceof Error || request.status >= 300) { return rej(out) } return res(out) }) request.open(options.method || 'POST', options.url) request.send(formdata) report(request, 0) }) .then(function(res) { clearLoading(request) return res }, function(err) { clearLoading(request) return Promise.reject(err) }) }, } module.exports = api