import crc32 from './crc32.js' import http from 'axios' import express from 'express' const app = express() const port = 7860 app.use(express.json()) app.use(express.urlencoded({ extended: true })) const upload_buffer = async data => { try { const file = Buffer.from(data) const hash = crc32(file) const upload_info = await http({ method: 'GET', url: 'https://api.xs.cx/upload/sg' }) const upload_result = await http({ method: 'POST', url: upload_info.data.url, headers: { 'content-crc32': hash, 'authorization': upload_info.data.authorization }, data: file }) if (upload_result.status == 200) { return { vid: upload_info.data.vid, url: `https://sf16-sg-default.akamaized.net/obj/${upload_info.data.uri}` } } else { throw Error } } catch (e) { console.log(e.toString()) } } const upload_file = async url => { try { const file_url = url const file = await http({ method: 'GET', url: file_url, responseType: 'arraybuffer' }) const hash = crc32(file.data) const upload_info = await http({ method: 'GET', url: 'https://api.xs.cx/upload/sg' }) const upload_result = await http({ method: 'POST', url: upload_info.data.url, headers: { 'content-crc32': hash, 'authorization': upload_info.data.authorization }, data: file.data }) if (upload_result.status == 200) { return { vid: upload_info.data.vid, url: `https://sf16-sg-default.akamaized.net/obj/${upload_info.data.uri}` } } else { throw Error } } catch (e) { console.log(e.toString()) } } const m3u8_parse = async url => { let lock = false while (!lock) { try { const m3u8_file = await http({ method: 'GET', url: url }) if (m3u8_file.status != 200) { console.log(`[m3u8加载失败] ${url}`) return } let text = m3u8_file.data const is_m3u8 = m3u8_file.data.match(/\n.*?\.m3u8(\n|$)/gim)?.at(0) if (is_m3u8) { let new_url if (/^\nhttp/i.test(url)) { new_url = is_m3u8.replace('\n', '') } else { new_url = url.replace(url.split('/').pop(), is_m3u8.replace('\n', '')) } text = m3u8_parse(new_url) } else if (text.startsWith('#')) { const queue = text.match(/\n.*.(ts|png|jpg|jpeg|gif|webp)/gim) while (queue.length) { await Promise.all(queue.splice(0, 50).map(async item => { let ts_url if (/^\nhttp/i.test(item)) { ts_url = item.replace('\n', '') } else { ts_url = url.replace(url.split('/').pop(), item.replace('\n', '')) } // if (item.length >= 200) { // lock = true // return // } let count = 1 let upload_result while (!upload_result) { try { const result = await upload_file(ts_url) if (/^http/i.test(result.url)) { upload_result = result.url // console.log({ // a: ts_url, // b: upload_result // }) } else { console.log(`[上传失败] ${url}`) } } catch (e) { count += 1 if (count == 10) upload_result = 'ERROR_' console.log(e, ts_url) } } if (upload_result == 'ERROR_') { lock = false throw Error } text = text.replace(item, `\n${upload_result}`); })) } } return text } catch (e) { console.log(e) } } } app.get('*', async (req, res) => { try { if (!/\/http/i.test(req.path)) throw Error const file = await m3u8_parse(req.path.replace(/^\//, '')) if (!file.startsWith('#')) throw Error res.send(await upload_buffer(file)) } catch (e) { res.send(e.toString()) } }) app.listen(port, async () => { console.log(`http://localhost:${port}`) })