Skip to content

Commit e856e7f

Browse files
committed
version 1.3.0
- added support for wikipages
1 parent f83ae49 commit e856e7f

File tree

5 files changed

+128
-40
lines changed

5 files changed

+128
-40
lines changed

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
.idea
2+
.vim
23
.history
34
.git
45
.env

README.md

+15
Original file line numberDiff line numberDiff line change
@@ -59,8 +59,11 @@ NOTE: Windows users might need to run `npm i --production` in cmd with administr
5959
## .env / config.txt
6060

6161
```
62+
# Base configuration. Subreddit OR wikipage is required.
6263
# Base configuration. Subreddit is required.
6364
subreddit=r/talesfromtechsupport # Subreddit with r/
65+
wikipage=https://www.reddit.com/r/hfy/wiki/series/calamitys_shadow # wikipage link
66+
wikipage_title=Calamity's Shadow # wikipage title (same as ebook title)
6467
max_pages=10 # Maxium pages to loop trough
6568
6669
# Page. Values: new|top|hot|rising|controversial
@@ -85,6 +88,9 @@ [email protected] # Your whitelisted email (NOT YET AVAILABLE)
8588

8689
NOTE: config.txt is prioritized over .env
8790

91+
`wikipage` also requires `wikipage_title`
92+
if `wikipage` is set, `max_pages`, `page` and `from` is ignored.
93+
8894
After adding comments support, configuration gets little complicated.
8995

9096
Here is little explanation.
@@ -108,6 +114,15 @@ So in default configuration, if message thread have 4 indented replies, we only
108114

109115
# Changelog
110116

117+
### Release 1.3.0
118+
119+
```
120+
2022-06-18 - Wikipage support
121+
122+
- added support for wikipages, ex. https://www.reddit.com/r/hfy/wiki/series/calamitys_shadow
123+
Reddit2Ebook automatically lists all post links and download those posts
124+
```
125+
111126
### Release 1.2.0
112127

113128
```

config.default.txt

+4-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
1-
# Base configuration. Subreddit is required.
1+
# Base configuration. Subreddit OR wikipage is required.
22
subreddit=r/talesfromtechsupport
3+
# wikipage=https://www.reddit.com/r/hfy/wiki/series/calamitys_shadow
4+
# wikipage_title=Calamity's Shadow
5+
36
max_pages=10
47

58
# Page. Values: new|top|hot|rising|controversial

index.js

+103-37
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,14 @@ const dotenv = require('dotenv').config({ path: path })
1313
let epub
1414
let maxPages = process.env.max_pages - 1
1515
let currentPage = 0
16-
const subreddit = process.env.subreddit
16+
let subreddit = process.env.subreddit
1717
const page = process.env.page || 'new'
1818
const from = process.env.from || 'all'
1919
let url = ''
2020
let urlExtra = ''
2121
let metadata = {}
2222
let comments_include = false
23+
let wikiLinks = []
2324

2425
//one request per second
2526
const axios = axiosClass.create()
@@ -34,9 +35,40 @@ async function main() {
3435
process.exit()
3536
}
3637

38+
if (process.env.wikipage !== undefined) {
39+
await axios
40+
.get(process.env.wikipage + '.json')
41+
.then(async r => {
42+
if (r.data.kind !== 'wikipage') {
43+
console.log('Invalid wikipage link')
44+
await pause()
45+
process.exit()
46+
}
47+
let regexp = /\((https.*\/comments\/.*)\)/g
48+
let matches = r.data.data.content_md.matchAll(regexp)
49+
for (const match of matches) {
50+
wikiLinks.push(match[1])
51+
}
52+
})
53+
.catch(async _ => {
54+
console.log('Invalid wikipage link')
55+
await pause()
56+
process.exit()
57+
})
58+
if (wikiLinks.length === 0) {
59+
console.log('No links found in wikipage')
60+
await pause()
61+
process.exit()
62+
} else {
63+
// set defaultvalues if wikiLinks is not empty
64+
maxPages = wikiLinks.length - 1
65+
subreddit = process.env.wikipage_title
66+
}
67+
}
68+
3769
// checking if configuration is valid and setting default values
38-
if (process.env.subreddit === undefined) {
39-
console.log('Missing subreddit from config file')
70+
if (process.env.subreddit === undefined && process.env.wikipage === undefined) {
71+
console.log('Missing subreddit or wikipage from config file')
4072
await pause()
4173
process.exit()
4274
}
@@ -65,10 +97,11 @@ async function main() {
6597

6698
url = '/' + page + '.json?limit=10&sort=' + page + urlExtra
6799

100+
let filename = wikiLinks.length > 0 ? subreddit.replace(/[^a-z0-9]/gi, '_').toLowerCase() : subreddit.split('/').pop()
68101
metadata = {
69102
id: Date.now(),
70-
title: subreddit,
71-
series: subreddit,
103+
title: subreddit.replace(/[^a-z0-9]/gi, ' '),
104+
series: subreddit.replace(/[^a-z0-9]/gi, ' '),
72105
sequence: 1,
73106
author: 'Anonymous',
74107
fileAs: 'Anonymous',
@@ -98,31 +131,41 @@ async function main() {
98131
process.env.comments_max_replies_indentation = process.env.comments_max_replies_indentation || 2
99132

100133
// just to get this as async function
101-
generateEbook()
134+
generateEbook(wikiLinks.length > 0)
102135
}
103136

104137
async function pause() {
105138
readlineSync.question('Press enter to continue...')
106139
}
107140

108-
async function generateEbook() {
109-
console.log('Creating ebook from: ' + subreddit + ' (' + page + ', links from ' + (['all', 'new'].includes(from) ? '' : 'past ') + from + ')' + (comments_include ? ' (comments enabled)' : ''))
141+
async function generateEbook(wikipage = false) {
142+
if (wikipage) {
143+
console.log('Generating wikipage ebook: ' + process.env.wikipage_title + (comments_include ? ' (comments enabled)' : ''))
144+
} else {
145+
console.log('Creating ebook from: ' + subreddit + ' (' + page + ', links from ' + (['all', 'new'].includes(from) ? '' : 'past ') + from + ')' + (comments_include ? ' (comments enabled)' : ''))
146+
}
110147

111148
//creating custom cover with subreddit as text
112149
await createCover()
113150
epub = makepub.document(metadata, './cover/cover.jpg')
114151
epub.addCSS('h1>a{color:inherit;text-decoration:none}.comment-parent{margin-left:0!important}.comment{margin-left:5px;padding-left:5px;border-left:1px solid gray;}')
115152

116-
await getContent('https://old.reddit.com/' + subreddit + url)
153+
if (wikipage) {
154+
await getWikipageContent()
155+
} else {
156+
await getContent('https://old.reddit.com/' + subreddit + url, wikipage)
157+
}
158+
159+
let filename = wikiLinks.length > 0 ? subreddit.replace(/[^a-z0-9]/gi, '_').toLowerCase() : subreddit.split('/').pop()
117160

118161
await epub.writeEPUB(
119162
function (e) {
120163
console.log('Error:', e)
121164
},
122165
'./output',
123-
subreddit.split('/').pop(),
166+
filename,
124167
async function () {
125-
ora('EPUB created to output/' + subreddit.split('/').pop() + '.epub\n')
168+
ora('EPUB created to output/' + filename + '.epub\n')
126169
.start()
127170
.succeed()
128171

@@ -140,32 +183,7 @@ async function getContent(url) {
140183
const spinner = ora('Current page: ' + (currentPage + 1) + '/' + (maxPages + 1)).start()
141184
spinner.start()
142185
await asyncForEach(r.data.data.children, async c => {
143-
// we only want selfposts and non-sticky posts
144-
if (!c.data.is_self || c.data.stickied) return
145-
let comments = ''
146-
147-
// load comments if they are enabled
148-
if (comments_include) {
149-
comments = await getComments(c.data.url.slice(0, -1) + '.json?sort=confidence')
150-
if (comments !== '') comments = '<br /><h3>Comments<hr /></h3>' + comments
151-
}
152-
153-
//add section to epub. Title as h1 with link. small text for author and date.
154-
epub.addSection(
155-
c.data.title,
156-
"<h1><a href='" +
157-
c.data.url +
158-
"'>" +
159-
c.data.title +
160-
'</a></h1>' +
161-
'<small><i>By</i> ' +
162-
c.data.author +
163-
' <i>on</i> ' +
164-
new Date(c.data.created * 1000).toISOString().split('T')[0] +
165-
'</small>' +
166-
decode(c.data.selftext_html).replace('<!-- SC_ON -->', '') +
167-
comments
168-
)
186+
await addPost(c)
169187
})
170188
spinner.succeed()
171189
process.stdout.write('\r')
@@ -180,6 +198,54 @@ async function getContent(url) {
180198
})
181199
}
182200

201+
async function getWikipageContent() {
202+
await asyncForEach(wikiLinks, async link => {
203+
await axios
204+
.get(link + '.json')
205+
.then(async r => {
206+
const spinner = ora('Current page: ' + (currentPage + 1) + '/' + (maxPages + 1)).start()
207+
spinner.start()
208+
await addPost(r.data[0].data.children[0])
209+
spinner.succeed()
210+
process.stdout.write('\r')
211+
212+
currentPage++
213+
})
214+
.catch(function (error) {
215+
console.log(error)
216+
})
217+
})
218+
}
219+
220+
async function addPost(c) {
221+
// we only want selfposts and non-sticky posts
222+
if (!c.data.is_self || c.data.stickied) return
223+
let comments = ''
224+
225+
// load comments if they are enabled
226+
if (comments_include) {
227+
comments = await getComments(c.data.url.slice(0, -1) + '.json?sort=confidence')
228+
if (comments !== '') comments = '<br /><h3>Comments<hr /></h3>' + comments
229+
}
230+
231+
//add section to epub. Title as h1 with link. small text for author and date.
232+
epub.addSection(
233+
c.data.title,
234+
"<h1><a href='" +
235+
c.data.url +
236+
"'>" +
237+
c.data.title +
238+
'</a></h1>' +
239+
'<small><i>By</i> ' +
240+
c.data.author +
241+
' <i>on</i> ' +
242+
new Date(c.data.created * 1000).toISOString().split('T')[0] +
243+
'</small>' +
244+
decode(c.data.selftext_html).replace('<!-- SC_ON -->', '') +
245+
comments
246+
)
247+
}
248+
183249
async function getComments(url) {
184250
// get comments from url
185251
const child = await axios(url)

package.json

+5-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "reddit2ebook",
3-
"version": "1.2.0",
3+
"version": "1.3.0",
44
"description": "Turns any subreddit (selftext) to ebook.",
55
"main": "index.js",
66
"dependencies": {
@@ -28,7 +28,10 @@
2828
"license": "ISC",
2929
"pkg": {
3030
"scripts": "index.js",
31-
"assets": ["./node_modules/@jimp/plugin-print/**/*", "./cover/**"]
31+
"assets": [
32+
"./node_modules/@jimp/plugin-print/**/*",
33+
"./cover/**"
34+
]
3235
},
3336
"bin": {
3437
"myapp": "./index.js"

0 commit comments

Comments
 (0)