]> git.r.bdr.sh - rbdr/linkding-linkblog-updater/blame - index.js
Make some of the values more generic
[rbdr/linkding-linkblog-updater] / index.js
CommitLineData
89326417
RBR
1const { exec } = require('child_process');
2const { resolve, join} = require('path');
3const { rm, writeFile } = require('fs/promises');
2390d230 4const { promisify } = require('util');
89326417
RBR
5const Pinboard = require('node-pinboard').default;
6
7const 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
65async function run() {
66 const pinboard = new Pinboard(internals.apiToken);
096cf8b1 67 const getPins = promisify(pinboard.all);
89326417
RBR
68 const addPin = promisify(pinboard.add);
69
89326417
RBR
70 const pins = await getPins({ tag: 'linkblog' });
71
28414efe 72 if (pins.length === 0) {
89326417
RBR
73 console.error('No links to post');
74 return;
75 }
76
278296c2
RBR
77 const title = internals.getTitle(pins);
78 const text = internals.getText(pins);
f0b2faff
RBR
79 const gemtext = internals.generateGemtext(title, text);
80 const filename = internals.slugify(title);
81
82 const gemfile = resolve(join(__dirname, `${filename}.gmi`));
89326417 83 await writeFile(gemfile, gemtext);
2390d230
RBR
84 await internals.exec(`blog --add ${gemfile}`);
85 await internals.exec(`blog --publish ${internals.blogUrl}`);
86 await internals.exec(`blog --publish-archive ${internals.archiveUrl}`);
89326417
RBR
87 await rm(gemfile);
88
28414efe 89 for (const pin of pins) {
89326417
RBR
90 await addPin({
91 url: pin.href,
92 description: pin.description,
93 extended: pin.extended,
94 dt: pin.time,
95 tags: pin.tags.replace('linkblog', 'linkblog-posted')
96 });
97 }
278296c2
RBR
98
99 if (internals.tootToken) {
100 await internals.toot(title);
101 }
89326417
RBR
102}
103
104run()
105 .then(() => process.exit(0))
106 .catch((err) => {
107 console.error(err);
108 process.exit(1);
109 })