--[[ A simple helper for storing binary data in a remote storage while returning a token, which then can be used to retrieve the data. Few caveats: - Data should not exceed 512 KB; - Data will be removed a few days after the last time it’s been accessed; - Tokens from removed data will be reused for the subsequent requests to keep tokens short, so if you’re going to try and access something aged, maybe store some CRC32 checksum along with token; - Everything is available publicly, so make sure to encrypt things if you’re uploading something personal; - Uploading the same data twice will yield the same token. General use case is if you need to transfer a few KB of data via a CSP online message, for example, and you know that the recipient will read the data straight away. Feel free to reimplement this logic in a different programming language if needed, but please keep in mind: - There are no guarantees it’ll keep working in current form (it is highly likely though); - To retrieve actual data, you’d need to read `X-Parcel-Xor-Key` and use that to XOR resulting data. Key is always 8 bytes long (but in header, it’s base64-encoded, so you need to decode it too). Its only purpose is to make sure my precious domain wouldn’t get nuked if somebody would use this service to share something that would trigger some antivirus; - Also, when recreating protocol, notice the use of “application/octet-stream” in headers. ]] ---@diagnostic disable local parcel = {} ---Store data. ---@param data binary ---@param callback fun(err: string?, token: string?) function parcel.store(data, callback) -- Rate limits on the backend apply before checking if a packet is already present, so it makes sense -- to reuse known tokens early. local cacheKey = string.format('.parcel.s.%s', bit.tohex(ac.checksumXXH(data))) local ready = ac.load(cacheKey) if type(ready) == 'string' then setTimeout(function () callback(nil, ready) end, 0.05) return end web.post('https://parcel.acstuff.club/', { ['content-type'] = 'application/octet-stream' }, data or '', function (err, response) local parsed = not err and response and JSON.parse(response.body) if parsed and type(parsed.token) == 'string' then ac.store(cacheKey, parsed.token) callback(nil, parsed.token) return else callback(parsed and parsed.error or err or 'Unknown error', nil) end end) end ---Retrieve data. ---@param token string ---@param callback fun(err: string?, data: binary?) function parcel.retrieve(token, callback) local cacheKey = string.format('.parcel.r.%s', bit.tohex(ac.checksumXXH(token))) local ready = ac.load(cacheKey) if type(ready) == 'string' then setTimeout(function () callback(nil, ready) end, 0.05) return end web.get('https://parcel.acstuff.club/%s' % token, { ['accept'] = 'application/octet-stream' }, function (err, response) if not err and response and response.body then local key = response.headers['x-parcel-xor-key'] if key then local decodedKey = ac.decodeBase64(key) if decodedKey and #decodedKey == 8 then local decrypted = string.xor(response.body, decodedKey) ac.store(cacheKey, decrypted) callback(nil, decrypted) return end end end callback(err or 'Unknown error', nil) end) end return parcel