]> git.r.bdr.sh - rbdr/linkding-linkblog-updater/blame - index.js
Remove references to pinboard
[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
5
6const internals = {
7 exec: promisify(exec),
2390d230 8
fdb5251c
RBR
9 apiUrl: process.env.API_URL,
10 apiToken: process.env.API_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 28
fdb5251c 29 return `=> ${post.url} ${post.title}\n${post.notes}`;
89326417 30 }).join('\n\n');
f0b2faff
RBR
31 },
32
33 getTitle(posts) {
89326417 34
f0b2faff 35 if (posts.length === 1) {
fdb5251c 36 return `Link: ${posts[0].title}`;
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`, {
fdb5251c 54 method: 'POST',
278296c2
RBR
55 headers: {
56 Authorization: `Bearer ${internals.tootToken}`,
57 },
58 body
59 });
fdb5251c
RBR
60 },
61
62 async getBookmarks() {
63
64 const url = join(internals.apiUrl, 'bookmarks') + '?q=%23linkblog';
65 const response = await fetch(url, {
66 headers: {
67 'Content-Type': 'application/json',
68 Authorization: `Token ${internals.apiToken}`
69 }
70 });
71 const data = await response.json();
72
73 return data.results;
74 },
278296c2 75
fdb5251c
RBR
76 async updateBookmark(bookmark) {
77
78 console.log(bookmark.tag_names);
79 console.log(bookmark.tag_names.map((tag) => tag === 'linkblog' ? 'linkblog-posted' : tag));
80
81 const url = join(internals.apiUrl, 'bookmarks', `${bookmark.id}`)
82 const response = await fetch(url, {
83 method: 'PATCH',
84 body: JSON.stringify(
85 {
86 tag_names: bookmark.tag_names.map((tag) => tag === 'linkblog' ? 'linkblog-posted' : tag)
87 }
88 ),
89 headers: {
90 'Content-Type': 'application/json',
91 Authorization: `Token ${internals.apiToken}`
92 }
93 });
94
95 const data = await response.text();
96 console.log(url);
97 console.log(data);
98 }
89326417
RBR
99};
100
101
102async function run() {
fdb5251c 103 const bookmarks = await internals.getBookmarks();
89326417 104
fdb5251c 105 if (bookmarks.length === 0) {
89326417
RBR
106 console.error('No links to post');
107 return;
108 }
109
fdb5251c
RBR
110 const title = internals.getTitle(bookmarks);
111 const text = internals.getText(bookmarks);
f0b2faff
RBR
112 const gemtext = internals.generateGemtext(title, text);
113 const filename = internals.slugify(title);
114
115 const gemfile = resolve(join(__dirname, `${filename}.gmi`));
89326417 116 await writeFile(gemfile, gemtext);
70dc59db
RBR
117 await internals.exec(`blog add ${gemfile}`);
118 await internals.exec(`blog publish ${internals.blogUrl}`);
119 await internals.exec(`blog publish-archive ${internals.archiveUrl}`);
89326417
RBR
120 await rm(gemfile);
121
fdb5251c
RBR
122 for (const bookmark of bookmarks) {
123 await internals.updateBookmark(bookmark);
89326417 124 }
278296c2
RBR
125
126 if (internals.tootToken) {
127 await internals.toot(title);
128 }
89326417
RBR
129}
130
131run()
132 .then(() => process.exit(0))
133 .catch((err) => {
134 console.error(err);
135 process.exit(1);
136 })