From 8dfd7c5d1af66b6e3242548bdb628c303b5d9c6f Mon Sep 17 00:00:00 2001 From: jphager2 Date: Sat, 6 Jan 2018 10:41:03 +0100 Subject: [PATCH] Download button --- src/ChapterList.js | 51 +++++++++++++++++++++++++++++++++++++++++++-- src/index.server.js | 41 +++++++++++++++++++++++++++++++++++- 2 files changed, 89 insertions(+), 3 deletions(-) diff --git a/src/ChapterList.js b/src/ChapterList.js index 1d159eb..45f1639 100644 --- a/src/ChapterList.js +++ b/src/ChapterList.js @@ -4,12 +4,16 @@ import './ChapterList.css'; class Chapter extends Component { constructor(props) { super(props); + this.id = this.props.chapter.id; this.toggleRead = this.toggleRead.bind(this); + this.download = this.download.bind(this); + this.downloadPoll = this.downloadPoll.bind(this); + this.downloadPollInterval = null; } toggleRead(e) { const chapter = this.props.chapter; - const url = `http://localhost:8999/chapters/${chapter.id}/read` + const url = `http://localhost:8999/chapters/${this.id}/read`; const button = e.target; fetch(url, {method: chapter.read ? 'DELETE' : 'POST'}) @@ -21,6 +25,49 @@ class Chapter extends Component { }) } + download(e) { + const url = `http://localhost:8999/chapters/${this.id}/download`; + const button = e.target; + + if (button.classList.contains('downloading')) { return; } + + button.classList.add('downloading'); + + fetch(url, {method: 'POST'}) + .then((res) => { + if (res.status !== 202 && res.status !== 409) { + throw new Error('Failed to download manga'); + } + this.downloadPollInterval = window.setInterval(() => this.downloadPoll(button), 1000); + }) + .catch((e) => { + console.error(e); + button.classList.remove('downloading'); + }); + } + + downloadPoll(button) { + if (!this.downloadPollInterval) { return; } + + fetch(`http://localhost:8999/manga/${this.id}/download`) + .then((res) => { + if (res.status === 409) { return; } + + if (res.status !== 200) { + throw new Error('Failed to download manga'); + } + + button.classList.remove('downloading'); + window.location.reload(); + }) + .catch((e) => { + console.error(e); + button.classList.remove('downloading'); + window.clearInterval(this.downloadPollInterval); + this.downloadPollInterval = null; + }); + } + render() { const chapter = this.props.chapter; @@ -31,7 +78,7 @@ class Chapter extends Component {
Mark as {chapter.read ? 'Un' : ''}read
-
Download
+
Download
); } diff --git a/src/index.server.js b/src/index.server.js index eb1da66..c68c4d3 100644 --- a/src/index.server.js +++ b/src/index.server.js @@ -128,7 +128,6 @@ app.post('/manga/:id/update', (req, res) => { cmd.stdout.on('data', data => out.concat(data)); cmd.stderr.on('data', data => err.concat(data)); cmd.on('close', code => { - fs.writeFile('/home/john/log', `code: ${code}, err: ${err}, out: ${out}, manga: ${JSON.stringify(manga)}, cmd: ${JSON.stringify(cmd)}`, () => {}); if (code !== 0) { console.error(err); } delete updatingSingleManga[id]; }); @@ -142,6 +141,46 @@ app.post('/manga/:id/update', (req, res) => { res.status(status).end(); }); +const downloadingSingleChapter = {}; + +app.get('/manga/:id/download', (req, res) => { + res.status(downloadingSingleChapter[req.params.id] ? 409 : 200).end(JSON.stringify(downloadingSingleChapter)); +}); + +app.post('/chapters/:id/download', (req, res) => { + const id = req.params.id; + + if (downloadingSingleChapter[id]) { + status = 409 + } else { + status = 202; + downloadingSingleChapter[id] = true; + + db('chapters') + .innerJoin('manga', 'chapters.manga_id', 'manga.id') + .select('manga.name AS manga', 'chapters.number') + .where('chapters.id', id) + .then(([{manga, number}]) => { + const cmd = spawn(MY_MANGA_PATH, ['download', manga, `--list=${number}`]); + const out = ''; + const err = ''; + + cmd.stdout.on('data', data => out.concat(data)); + cmd.stderr.on('data', data => err.concat(data)); + cmd.on('close', code => { + if (code !== 0) { console.error(err); } + delete downloadingSingleChapter[id]; + }); + }) + .catch((e) => { + console.error(e); + delete downloadingSingleChapter[id]; + }); + } + + res.status(status).end(); +}); + app.post('/chapters/:id/read', (req, res) => { const id = req.params.id;