1 | module.exports.publish = (options) => {
|
2 |
|
3 |
|
4 | 'use strong'
|
5 |
|
6 | const chalk = require('chalk')
|
7 | const request = require('superagent')
|
8 | const path = require('path')
|
9 | const osHomeDir = require('os').homedir()
|
10 | const fs = require('fs')
|
11 | const jsonfile = require('jsonfile')
|
12 | const manuscript = require('book-length')
|
13 | const arc = require('arc-bookiza')
|
14 |
|
15 | const location = path.join(osHomeDir, '.', '.bookizarc')
|
16 |
|
17 | arc.read(location)
|
18 | .then(data => {
|
19 | const bookizArc = JSON.parse(data)
|
20 | if (bookizArc.token === '') {
|
21 | throw new Error('BookizArc.token unavailable!')
|
22 | }
|
23 | initializeBookPress(bookizArc)
|
24 | })
|
25 | .catch(err => {
|
26 | console.log(chalk.bold.red('Unregistered client'))
|
27 | console.log(chalk.bold.cyan('Try $ bookiza register --help'))
|
28 | console.log(err)
|
29 | })
|
30 |
|
31 |
|
32 | function initializeBookPress (bookizArc) {
|
33 | const file = '.bookrc'
|
34 |
|
35 | jsonfile.readFile(file, (err, bookrc) => {
|
36 | if (err) {
|
37 | throw new Error('Couldn\'t read the arc.')
|
38 | }
|
39 | if (!(bookrc.hasOwnProperty('book_id'))) {
|
40 | requestBookId(bookizArc, bookrc, options.token)
|
41 | } else {
|
42 | patchBook(bookizArc, bookrc, options.token)
|
43 | }
|
44 | })
|
45 | }
|
46 |
|
47 | function requestBookId (bookizArc, bookrc, token = bookizArc.token) {
|
48 | if (token === undefined) {
|
49 | console.log(chalk.red('Cannot proceed without API_token'))
|
50 | return
|
51 | }
|
52 |
|
53 | const url = bookizArc.urls.baseURL
|
54 | const method = 'post'
|
55 |
|
56 | request[method](url)
|
57 | .send()
|
58 | .set('Accept', 'application/json')
|
59 | .set('Accept', 'application/bookiza.bubblin.v2')
|
60 | .set('Authorization', `Token token=${token}`)
|
61 | .end((err, res) => {
|
62 | if (!err && res.ok && res.body.status === 201 && res.body.id !== null) {
|
63 | bookrc.book_id = res.body.id
|
64 | fs.writeFileSync('.bookrc', JSON.stringify(bookrc, null, 2))
|
65 | patchBook(bookizArc, bookrc, token)
|
66 | } else {
|
67 | let errorMessage
|
68 | if (res && res.body.status === 401) {
|
69 | errorMessage = 'Authentication failed! Bad username/password?'
|
70 | } else if (res.body.status === 403) {
|
71 | errorMessage = 'Submission unauthorized!'
|
72 | } else {
|
73 | errorMessage = res.text
|
74 | }
|
75 | console.error(chalk.red(errorMessage))
|
76 | process.exit(1)
|
77 | }
|
78 | })
|
79 | }
|
80 |
|
81 | function patchBook (bookizArc, bookrc, token = bookizArc.token) {
|
82 | const book = {}
|
83 |
|
84 | book.title = bookrc.name || 'Untitled'
|
85 | book.has_page_numbers = bookrc.has_page_numbers || 'false'
|
86 | book.status = bookrc.status || 'draft'
|
87 | book.id = bookrc.book_id
|
88 |
|
89 | |
90 |
|
91 |
|
92 |
|
93 | const COMPONENTS = [
|
94 | { name: 'HEAD', path: 'head.html' },
|
95 | { name: 'HTML', path: 'body.html' },
|
96 | { name: 'CSS', path: 'style.css' },
|
97 | { name: 'JS', path: 'script.js' }
|
98 | ]
|
99 |
|
100 | const template = {}
|
101 |
|
102 | for (const templateIndex in COMPONENTS) {
|
103 | const templateComponentPath = path.join('build', 'templates', COMPONENTS[templateIndex].path)
|
104 | if (fs.existsSync(templateComponentPath)) {
|
105 | template[COMPONENTS[templateIndex].name] = fs.readFileSync(templateComponentPath, 'utf-8').toString()
|
106 | }
|
107 | }
|
108 |
|
109 | book.template_attributes = template
|
110 |
|
111 | |
112 |
|
113 |
|
114 | const cover = {}
|
115 |
|
116 | let toc = ''
|
117 | if (fs.existsSync(path.join('.', 'cover', 'toc.html'))) {
|
118 | toc = fs.readFileSync(path.join('.', 'cover', 'toc.html'), 'utf-8').toString()
|
119 | }
|
120 |
|
121 | if (bookrc.hasOwnProperty('cover')) {
|
122 | cover.punchline = bookrc.cover.punchline || ''
|
123 | cover.toc = toc
|
124 | cover.author_detail = bookrc.cover.author_detail || ''
|
125 | cover.colophon = bookrc.cover.colophon || ''
|
126 | cover.synopsis = bookrc.cover.synopsis || ''
|
127 | }
|
128 |
|
129 | book.cover_attributes = cover
|
130 |
|
131 | const length = manuscript.length()
|
132 |
|
133 | let pages = []
|
134 |
|
135 | const PAGES_CHUNK_SIZE = 50
|
136 |
|
137 | let batchStart = 1
|
138 | let batchEnd = length < PAGES_CHUNK_SIZE ? length : PAGES_CHUNK_SIZE
|
139 |
|
140 | let requestStatus = []
|
141 |
|
142 | do {
|
143 | for (let pageNo = batchStart; pageNo <= batchEnd; pageNo++) {
|
144 | const page = {}
|
145 |
|
146 | page.book_id = book.id
|
147 |
|
148 | page.page_no = pageNo
|
149 | for (const index in COMPONENTS) {
|
150 | const componentPath = path.join('build', 'manuscript', `page-${pageNo}`, COMPONENTS[index].path)
|
151 | if (fs.existsSync(componentPath)) {
|
152 | page[COMPONENTS[index].name] = fs.readFileSync(componentPath, 'utf-8').toString()
|
153 | }
|
154 | }
|
155 | pages.push(page)
|
156 | }
|
157 |
|
158 | book.pages_attributes = pages
|
159 |
|
160 | const bookJson = {}
|
161 |
|
162 | bookJson.book = book
|
163 | bookJson.length = length
|
164 |
|
165 | const url = bookizArc.urls.baseURL + book.id
|
166 | const method = 'patch'
|
167 |
|
168 | request[method](url)
|
169 | .send(encodeURI(JSON.stringify(bookJson)))
|
170 | .set('Accept', 'application/json')
|
171 | .set('Accept', 'application/bookiza.bubblin.v2')
|
172 | .set('Authorization', `Token token=${token}`)
|
173 | .set('gzip', 'true')
|
174 | .end((err, res) => {
|
175 | process.stdout.write(chalk.bold.blue('🖇'))
|
176 |
|
177 | requestStatus.push(1)
|
178 |
|
179 | if (batchStart > length && batchEnd === length) {
|
180 | printComplete(res)
|
181 | }
|
182 |
|
183 | if (!(!err && res.ok && res.body.status === 200)) {
|
184 | let errorMessage
|
185 | if (res && res.body.status === 401) {
|
186 | errorMessage = 'Authentication failed! Bad username/password?'
|
187 | } else if (res.body.status === 403) {
|
188 | errorMessage = 'Submission unauthorized!'
|
189 | } else {
|
190 | errorMessage = res.text
|
191 | }
|
192 | console.error(chalk.red(errorMessage))
|
193 | process.exit(1)
|
194 | }
|
195 | })
|
196 |
|
197 | batchStart = batchEnd + 1
|
198 | batchEnd = (batchEnd + PAGES_CHUNK_SIZE) > length ? length : (batchEnd + PAGES_CHUNK_SIZE)
|
199 |
|
200 | pages = []
|
201 | } while (batchStart <= length)
|
202 |
|
203 | function float2int (value) {
|
204 | return value | 0
|
205 | }
|
206 |
|
207 | function printComplete (response) {
|
208 | if (requestStatus.every(elem => elem === 1) && requestStatus.length === float2int(length / PAGES_CHUNK_SIZE) + 1) {
|
209 |
|
210 | bookrc.book_url = response.body.url
|
211 | fs.writeFileSync('.bookrc', JSON.stringify(bookrc, null, 2))
|
212 |
|
213 |
|
214 | console.log(chalk.bold.cyan(' [100%] Manuscript patch completed successfully.'))
|
215 | console.log(chalk.bold.yellow(' Book was patched into your Bubblin Account. Check online @ https://bubblin.io!'))
|
216 | }
|
217 | }
|
218 | }
|
219 | }
|