prettier upload page
This commit is contained in:
@@ -4,40 +4,7 @@
|
|||||||
<title>Send To Kobo</title>
|
<title>Send To Kobo</title>
|
||||||
<meta charset="utf-8"/>
|
<meta charset="utf-8"/>
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
|
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
|
||||||
<style>
|
<link rel="stylesheet" type="text/css" href="/style.css"/>
|
||||||
.wrapper {
|
|
||||||
margin: 0 20px;
|
|
||||||
}
|
|
||||||
h1 {
|
|
||||||
font-weight: normal;
|
|
||||||
font-style: italic;
|
|
||||||
}
|
|
||||||
#key {
|
|
||||||
font-size: 3.5em;
|
|
||||||
display: block;
|
|
||||||
letter-spacing: 0.1em;
|
|
||||||
margin: 10px 0;
|
|
||||||
}
|
|
||||||
.center {
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
#keygen, #downloadlink {
|
|
||||||
background: #CCC;
|
|
||||||
border: none;
|
|
||||||
color: black;
|
|
||||||
font-style: italic;
|
|
||||||
padding: 0.6em 1.3em;
|
|
||||||
line-height: 1.6;
|
|
||||||
display: inline-block;
|
|
||||||
}
|
|
||||||
#keygen:focus {
|
|
||||||
background: black;
|
|
||||||
color: white;
|
|
||||||
}
|
|
||||||
#downloads {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
|
||||||
|
|||||||
26
index.js
26
index.js
@@ -11,9 +11,10 @@ const { spawn } = require('child_process')
|
|||||||
|
|
||||||
const expireDelay = 20
|
const expireDelay = 20
|
||||||
const port = 3001
|
const port = 3001
|
||||||
|
const maxFileSize = 1024 * 1024 * 400
|
||||||
|
|
||||||
const uniqueRandom = (minimum, maximum) => {
|
function uniqueRandom (minimum, maximum) {
|
||||||
let previousValue;
|
let previousValue
|
||||||
return function random() {
|
return function random() {
|
||||||
const number = Math.floor(
|
const number = Math.floor(
|
||||||
(Math.random() * (maximum - minimum + 1)) + minimum
|
(Math.random() * (maximum - minimum + 1)) + minimum
|
||||||
@@ -51,10 +52,9 @@ function expireKey (key) {
|
|||||||
return timer
|
return timer
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const random = uniqueRandom(1000, 9999)
|
const random = uniqueRandom(1000, 9999)
|
||||||
|
|
||||||
const app = new Koa()
|
const app = new Koa()
|
||||||
|
app.context.keys = new Map()
|
||||||
const router = new Router()
|
const router = new Router()
|
||||||
const upload = multer({
|
const upload = multer({
|
||||||
storage: multer.diskStorage({
|
storage: multer.diskStorage({
|
||||||
@@ -68,7 +68,7 @@ const upload = multer({
|
|||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
limits: {
|
limits: {
|
||||||
fileSize: 1024 * 1024 * 400,
|
fileSize: maxFileSize,
|
||||||
files: 1
|
files: 1
|
||||||
},
|
},
|
||||||
fileFilter: (req, file, cb) => {
|
fileFilter: (req, file, cb) => {
|
||||||
@@ -87,9 +87,6 @@ const upload = multer({
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
app.context.keys = new Map()
|
|
||||||
|
|
||||||
|
|
||||||
router.get('/generate', async ctx => {
|
router.get('/generate', async ctx => {
|
||||||
const agent = ctx.get('user-agent')
|
const agent = ctx.get('user-agent')
|
||||||
if (!agent.includes('Kobo')) {
|
if (!agent.includes('Kobo')) {
|
||||||
@@ -121,7 +118,6 @@ router.get('/generate', async ctx => {
|
|||||||
ctx.body = key
|
ctx.body = key
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
router.get('/download/:key', async ctx => {
|
router.get('/download/:key', async ctx => {
|
||||||
const key = ctx.params.key
|
const key = ctx.params.key
|
||||||
const info = ctx.keys.get(key)
|
const info = ctx.keys.get(key)
|
||||||
@@ -138,7 +134,6 @@ router.get('/download/:key', async ctx => {
|
|||||||
ctx.attachment(info.file.name)
|
ctx.attachment(info.file.name)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
router.post('/upload', upload.single('file'), async ctx => {
|
router.post('/upload', upload.single('file'), async ctx => {
|
||||||
const key = ctx.request.body.key
|
const key = ctx.request.body.key
|
||||||
|
|
||||||
@@ -225,6 +220,10 @@ router.get('/status/:key', async ctx => {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
router.get('/style.css', async ctx => {
|
||||||
|
await sendfile(ctx, 'style.css')
|
||||||
|
})
|
||||||
|
|
||||||
router.get('/', async ctx => {
|
router.get('/', async ctx => {
|
||||||
const agent = ctx.get('user-agent')
|
const agent = ctx.get('user-agent')
|
||||||
console.log(agent)
|
console.log(agent)
|
||||||
@@ -237,7 +236,8 @@ app.use(router.allowedMethods())
|
|||||||
|
|
||||||
fs.rmdir('uploads', {recursive: true}, (err) => {
|
fs.rmdir('uploads', {recursive: true}, (err) => {
|
||||||
if (err) throw err
|
if (err) throw err
|
||||||
mkdirp.sync('uploads')
|
mkdirp('uploads').then (() => {
|
||||||
app.listen(port)
|
app.listen(port)
|
||||||
console.log('server is listening on port ' + port)
|
console.log('server is listening on port ' + port)
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|||||||
48
style.css
Normal file
48
style.css
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
|
||||||
|
.wrapper {
|
||||||
|
margin: 0 auto;
|
||||||
|
padding: 0 20px;
|
||||||
|
max-width: 600px;
|
||||||
|
}
|
||||||
|
h1 {
|
||||||
|
font-weight: normal;
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
#key {
|
||||||
|
font-size: 3.5em;
|
||||||
|
display: block;
|
||||||
|
letter-spacing: 0.1em;
|
||||||
|
margin: 10px 0;
|
||||||
|
}
|
||||||
|
.center {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
.right {
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
#keygen, #downloadlink {
|
||||||
|
background: #CCC;
|
||||||
|
border: none;
|
||||||
|
color: black;
|
||||||
|
font-style: italic;
|
||||||
|
padding: 0.6em 1.3em;
|
||||||
|
line-height: 1.6;
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
#keygen:focus {
|
||||||
|
background: black;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
#downloads {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#keyinput {
|
||||||
|
font-size: 3.5em;
|
||||||
|
width: 4em;
|
||||||
|
text-align: center;
|
||||||
|
font-family: serif;
|
||||||
|
}
|
||||||
28
upload.html
28
upload.html
@@ -4,17 +4,31 @@
|
|||||||
<title>Send To Kobo</title>
|
<title>Send To Kobo</title>
|
||||||
<meta charset="utf-8"/>
|
<meta charset="utf-8"/>
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
|
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
|
||||||
|
<link rel="stylesheet" type="text/css" href="/style.css"/>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
|
||||||
<h1>Send to Kobo</h1>
|
<div class="wrapper">
|
||||||
|
<h1 class="center">Send to Kobo</h1>
|
||||||
|
|
||||||
<form action="/upload" method="post" enctype="multipart/form-data">
|
<form action="/upload" method="post" enctype="multipart/form-data">
|
||||||
<input type="text" name="key" autocomplete="off" placeholder="Key" size="6" required /><br/>
|
<table style="margin: 0 auto;" cellpadding=10 cellspacing=0>
|
||||||
<input type="file" name="file" accept=".epub,application/epub+zip" required /><br/>
|
<tr><td class="right">Unique key</td><td><input type="text" name="key" id="keyinput" autocomplete="off" inputmode="numeric" pattern="\d\d\d\d" placeholder="- - - -" required /></td></tr>
|
||||||
<label><input type="checkbox" name="kepubify" checked /> Kepubify</label><br/>
|
<tr><td class="right">EPUB file</td><td><input type="file" name="file" accept=".epub,application/epub+zip" required /></td></tr>
|
||||||
<input type="submit" value="Upload" />
|
<tr><td class="right"><label for="kepubify">Kepubify</label></td><td><input type="checkbox" name="kepubify" id="kepubify" checked /></td></tr>
|
||||||
</form>
|
<tr><td></td><td><input type="submit" value="Upload" /></td></tr>
|
||||||
|
</table>
|
||||||
|
</form>
|
||||||
|
<br/>
|
||||||
|
<div style="padding: 15px; text-align: justify;">
|
||||||
|
<p>Go this this page on your Kobo ereader and you see a unique key. Enter it in this form and upload an ebook and it will appear as a download link on the ereader. Your ebook will be stored on the server as long as the Kobo is viewing the unique key and is connected to wifi. It will be deleted when the key expires about 30 seconds after you close the browser/generate a new key/disable wifi on your Kobo.</p>
|
||||||
|
<p>By using this tool you agree that the ebook you upload is processed on the server and stored for a short time.</p>
|
||||||
|
</div>
|
||||||
|
<hr/>
|
||||||
|
<div class="center">
|
||||||
|
Created by djazz. Powered by <a href="https://koajs.com/" target="_blank">Koa</a> and <a href="https://pgaskin.net/kepubify/" target="_blank">Kepubify</a>.
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
Reference in New Issue
Block a user