Created
July 26, 2020 12:18
-
-
Save winguse/211d525d29d8a00353d5fcd6480f5dd0 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const http = require('http'); | |
const { spawn } = require('child_process'); | |
const jobs = {}; | |
setInterval(() => { | |
Object.keys(jobs).forEach(url => { | |
const {ts} = jobs[url]; | |
if (Date.now() - ts > 24 * 3600 * 1000) { | |
delete jobs[url]; | |
} | |
}) | |
}, 60 * 1000); | |
function download(url) { | |
if (jobs[url]) return; | |
const info = { | |
stdOut: '', | |
stdErr: '', | |
code: undefined, | |
ts: Date.now(), | |
}; | |
jobs[url] = info; | |
const job = spawn('youtube-dl', [url]); | |
job.stdout.on('data', (data) => { | |
info.stdOut += data; | |
console.log(`${url} stdout: ${data}`); | |
}); | |
job.stderr.on('data', (data) => { | |
info.stdErr += data; | |
console.error(`${url} stderr: ${data}`); | |
}); | |
job.on('close', (code) => { | |
info.code = code; | |
console.log(`${url} exit with code ${code}`); | |
}); | |
} | |
const server = http.createServer((req, res) => { | |
if (req.method === 'GET' && req.url && req.url.endsWith('/info.json')) { | |
res.writeHead(200, { | |
'content-type': 'application/json; utf-8', | |
}); | |
res.end(JSON.stringify(jobs)); | |
} else if (req.method === 'GET') { | |
res.writeHead(200, { | |
'content-type': 'text/html; utf-8', | |
}); | |
res.end(` | |
<style> | |
html,body{ | |
margin: 0; | |
padding: 0; | |
height: 100%; | |
} | |
.note { | |
text-align: center; | |
line-height: 3em; | |
font-size: 1em; | |
} | |
.verticalAccordion { | |
width: 100%; | |
} | |
.verticalAccordion ul { | |
width: 100%; | |
margin: 0; | |
padding: 0; | |
} | |
.verticalAccordion li { | |
list-style: none outside none; | |
display: block; | |
margin: 0; | |
padding: 0; | |
height: 40px; | |
width: 100%; | |
overflow: hidden; | |
background: #f0f0f0; | |
transition: height 0.3s ease-in-out; | |
} | |
.verticalAccordion h3 { | |
margin: 0; | |
padding: 10px; | |
height: 19px; | |
border-top: 1px solid #f0f0f0; | |
text-transform: uppercase; | |
color: #000; | |
background: #ccc; | |
cusor: pointer; | |
position: relative; | |
} | |
.verticalAccordion h3:before { | |
content:""; | |
border: 5px solid #000; | |
border-color: #000 transparent transparent; | |
position: absolute; | |
right: 10px; | |
top: 15px; | |
width: 0; | |
height: 0; | |
} | |
.verticalAccordion div { | |
margin: 0; | |
overflow: auto; | |
padding: 10px; | |
height: 220px; | |
} | |
.verticalAccordion li:hover { | |
height: 280px; | |
} | |
.verticalAccordion li:hover h3 { | |
color: #fff; | |
background: #000; | |
} | |
.verticalAccordion li:hover h3:before { | |
border-color: transparent transparent transparent #fff; | |
} | |
</style> | |
<body> | |
<h1 class="note">Drop the URL here.</h1> | |
<div class="verticalAccordion"> | |
<ul id="ul"> | |
</ul> | |
</div> | |
</body> | |
<script> | |
async function fetchInfo() { | |
const res = await fetch('./info.json'); | |
const jobs = await res.json(); | |
Object.keys(jobs).forEach(url => { | |
const ul = document.querySelector('#ul'); | |
let li = document.querySelector(\`li[data-url='\${url}']\`); | |
if (!li) { | |
li = document.createElement('li'); | |
li.dataset.url = url; | |
const h3 = document.createElement('h3'); | |
h3.innerText = url; | |
li.append(h3); | |
const div = document.createElement('div'); | |
li.append(div); | |
const stdout = document.createElement('h4') | |
stdout.innerText = 'StdOut'; | |
const stderr = document.createElement('h4') | |
stderr.innerText = 'StdErr'; | |
div.append(document.createElement('p')); | |
div.append(stdout); | |
div.append(document.createElement('pre')); | |
div.append(stderr); | |
div.append(document.createElement('pre')); | |
ul.append(li); | |
} | |
const {code, stdOut, stdErr, ts} = jobs[url]; | |
li.querySelector('p').innerText = \`\${new Date(ts)}, \${ code === undefined ? 'processing...' : 'exit code: ' + code}\`; | |
const [stdoutEle, stderrEle] = li.querySelectorAll('pre'); | |
stdoutEle.innerText = stdOut; | |
stderrEle.innerText = stdErr; | |
}); | |
setTimeout(fetchInfo, 20 * 1000) | |
} | |
fetchInfo(); | |
window.addEventListener("drop", async e => { | |
e.preventDefault(); | |
e.stopPropagation(); | |
await fetch('.', { method: 'POST', body: e.dataTransfer.getData('URL') }) | |
fetchInfo(); | |
}); | |
window.addEventListener("dragover", e => e.preventDefault()); | |
</script>` | |
); | |
} else { | |
let body = ''; | |
req.on('data', data => { | |
body += data; | |
}); | |
req.on('end', () => { | |
try { | |
new URL(body); | |
download(body); | |
res.writeHead(204); | |
res.end(); | |
} catch (e) { | |
res.writeHead(403); | |
res.end('error url') | |
} | |
}); | |
} | |
}); | |
server.listen(4040, "127.0.0.1"); | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment