]>
Commit | Line | Data |
---|---|---|
89326417 RBR |
1 | const { exec } = require('child_process'); |
2 | const { resolve, join} = require('path'); | |
3 | const { rm, writeFile } = require('fs/promises'); | |
2390d230 | 4 | const { promisify } = require('util'); |
89326417 RBR |
5 | const Pinboard = require('node-pinboard').default; |
6 | ||
7 | const internals = { | |
8 | exec: promisify(exec), | |
2390d230 | 9 | |
89326417 | 10 | apiToken: process.env.PINBOARD_TOKEN, |
2390d230 RBR |
11 | blogUrl: process.env.BLOG_URL, |
12 | archiveUrl: process.env.ARCHIVE_URL, | |
9d9552d1 RBR |
13 | blogPublicUrl: process.env.BLOG_PUBLIC_URL, |
14 | archivePublicUrl: process.env.ARCHIVE_PUBLIC_URL, | |
278296c2 | 15 | tootToken: process.env.TOOT_TOKEN, |
9d9552d1 | 16 | mastodonDomain: process.env.MASTODON_DOMAIN, |
2390d230 | 17 | |
89326417 RBR |
18 | date: (new Date()).toISOString().split('T')[0], |
19 | ||
f0b2faff | 20 | generateGemtext(title, text) { |
89326417 | 21 | |
f0b2faff RBR |
22 | return `# ${title}\n\n${text}`; |
23 | }, | |
89326417 | 24 | |
f0b2faff RBR |
25 | getText(posts) { |
26 | ||
278296c2 | 27 | return posts.map((post) => { |
f0b2faff RBR |
28 | |
29 | return `=> ${post.href} ${post.description}\n${post.extended}`; | |
89326417 | 30 | }).join('\n\n'); |
f0b2faff RBR |
31 | }, |
32 | ||
33 | getTitle(posts) { | |
89326417 | 34 | |
f0b2faff | 35 | if (posts.length === 1) { |
278296c2 | 36 | return `Link: ${posts[0].description}`; |
f0b2faff RBR |
37 | } |
38 | return `${posts.length} links for ${internals.date}`; | |
39 | }, | |
40 | ||
41 | slugify(text) { | |
42 | ||
43 | return text.toLowerCase().replace(/[^a-z0-9 ]/g, '').replace(/ +/g, '-') | |
278296c2 RBR |
44 | }, |
45 | ||
46 | async toot(title) { | |
47 | ||
48 | const body = new FormData(); | |
49 | body.set( | |
50 | 'status', | |
9d9552d1 | 51 | `New post: ${title}\n\nAvailable on:\n\nāļø the gemini archive ${internals.archivePublicUrl}\n\n or, the ephemeral blog š: ${internals.blogPublicUrl}` |
278296c2 | 52 | ); |
9d9552d1 | 53 | return fetch(`https://${internals.mastodonDomain}/api/v1/statuses`, { |
278296c2 RBR |
54 | method: 'post', |
55 | headers: { | |
56 | Authorization: `Bearer ${internals.tootToken}`, | |
57 | }, | |
58 | body | |
59 | }); | |
89326417 | 60 | } |
278296c2 | 61 | |
89326417 RBR |
62 | }; |
63 | ||
64 | ||
65 | async function run() { | |
66 | const pinboard = new Pinboard(internals.apiToken); | |
89326417 | 67 | |
70dc59db | 68 | const pins = await pinboard.all({ tag: 'linkblog' }); |
89326417 | 69 | |
28414efe | 70 | if (pins.length === 0) { |
89326417 RBR |
71 | console.error('No links to post'); |
72 | return; | |
73 | } | |
74 | ||
278296c2 RBR |
75 | const title = internals.getTitle(pins); |
76 | const text = internals.getText(pins); | |
f0b2faff RBR |
77 | const gemtext = internals.generateGemtext(title, text); |
78 | const filename = internals.slugify(title); | |
79 | ||
80 | const gemfile = resolve(join(__dirname, `${filename}.gmi`)); | |
89326417 | 81 | await writeFile(gemfile, gemtext); |
70dc59db RBR |
82 | await internals.exec(`blog add ${gemfile}`); |
83 | await internals.exec(`blog publish ${internals.blogUrl}`); | |
84 | await internals.exec(`blog publish-archive ${internals.archiveUrl}`); | |
89326417 RBR |
85 | await rm(gemfile); |
86 | ||
28414efe | 87 | for (const pin of pins) { |
70dc59db | 88 | await pinboard.add({ |
89326417 RBR |
89 | url: pin.href, |
90 | description: pin.description, | |
91 | extended: pin.extended, | |
92 | dt: pin.time, | |
93 | tags: pin.tags.replace('linkblog', 'linkblog-posted') | |
94 | }); | |
95 | } | |
278296c2 RBR |
96 | |
97 | if (internals.tootToken) { | |
98 | await internals.toot(title); | |
99 | } | |
89326417 RBR |
100 | } |
101 | ||
102 | run() | |
103 | .then(() => process.exit(0)) | |
104 | .catch((err) => { | |
105 | console.error(err); | |
106 | process.exit(1); | |
107 | }) |