]>
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 | |
6 | const 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 | |
fe344d4e RBR |
29 | const title = post.title || post.website_title |
30 | return `=> ${post.url} ${title}\n${post.notes}`; | |
89326417 | 31 | }).join('\n\n'); |
f0b2faff RBR |
32 | }, |
33 | ||
34 | getTitle(posts) { | |
89326417 | 35 | |
fe344d4e RBR |
36 | const title = posts[0].title || posts[0].website_title |
37 | ||
f0b2faff | 38 | if (posts.length === 1) { |
fe344d4e | 39 | return `Link: ${title}`; |
f0b2faff RBR |
40 | } |
41 | return `${posts.length} links for ${internals.date}`; | |
42 | }, | |
43 | ||
44 | slugify(text) { | |
45 | ||
46 | return text.toLowerCase().replace(/[^a-z0-9 ]/g, '').replace(/ +/g, '-') | |
278296c2 RBR |
47 | }, |
48 | ||
49 | async toot(title) { | |
50 | ||
51 | const body = new FormData(); | |
52 | body.set( | |
53 | 'status', | |
9d9552d1 | 54 | `New post: ${title}\n\nAvailable on:\n\nāļø the gemini archive ${internals.archivePublicUrl}\n\n or, the ephemeral blog š: ${internals.blogPublicUrl}` |
278296c2 | 55 | ); |
9d9552d1 | 56 | return fetch(`https://${internals.mastodonDomain}/api/v1/statuses`, { |
fdb5251c | 57 | method: 'POST', |
278296c2 RBR |
58 | headers: { |
59 | Authorization: `Bearer ${internals.tootToken}`, | |
60 | }, | |
61 | body | |
62 | }); | |
fdb5251c RBR |
63 | }, |
64 | ||
65 | async getBookmarks() { | |
66 | ||
67 | const url = join(internals.apiUrl, 'bookmarks') + '?q=%23linkblog'; | |
68 | const response = await fetch(url, { | |
69 | headers: { | |
70 | 'Content-Type': 'application/json', | |
71 | Authorization: `Token ${internals.apiToken}` | |
72 | } | |
73 | }); | |
74 | const data = await response.json(); | |
75 | ||
76 | return data.results; | |
77 | }, | |
278296c2 | 78 | |
fdb5251c RBR |
79 | async updateBookmark(bookmark) { |
80 | ||
fdb5251c RBR |
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 | }); | |
fdb5251c | 94 | } |
89326417 RBR |
95 | }; |
96 | ||
97 | ||
98 | async function run() { | |
fdb5251c | 99 | const bookmarks = await internals.getBookmarks(); |
89326417 | 100 | |
fdb5251c | 101 | if (bookmarks.length === 0) { |
89326417 RBR |
102 | console.error('No links to post'); |
103 | return; | |
104 | } | |
105 | ||
fdb5251c RBR |
106 | const title = internals.getTitle(bookmarks); |
107 | const text = internals.getText(bookmarks); | |
f0b2faff RBR |
108 | const gemtext = internals.generateGemtext(title, text); |
109 | const filename = internals.slugify(title); | |
110 | ||
111 | const gemfile = resolve(join(__dirname, `${filename}.gmi`)); | |
89326417 | 112 | await writeFile(gemfile, gemtext); |
70dc59db RBR |
113 | await internals.exec(`blog add ${gemfile}`); |
114 | await internals.exec(`blog publish ${internals.blogUrl}`); | |
115 | await internals.exec(`blog publish-archive ${internals.archiveUrl}`); | |
89326417 RBR |
116 | await rm(gemfile); |
117 | ||
fdb5251c RBR |
118 | for (const bookmark of bookmarks) { |
119 | await internals.updateBookmark(bookmark); | |
89326417 | 120 | } |
278296c2 RBR |
121 | |
122 | if (internals.tootToken) { | |
123 | await internals.toot(title); | |
124 | } | |
89326417 RBR |
125 | } |
126 | ||
127 | run() | |
128 | .then(() => process.exit(0)) | |
129 | .catch((err) => { | |
130 | console.error(err); | |
131 | process.exit(1); | |
132 | }) |