const { resolve, join} = require('path');
const { rm, writeFile } = require('fs/promises');
const { promisify } = require('util');
-const Pinboard = require('node-pinboard').default;
const internals = {
exec: promisify(exec),
- apiToken: process.env.PINBOARD_TOKEN,
+ apiUrl: process.env.API_URL,
+ apiToken: process.env.API_TOKEN,
blogUrl: process.env.BLOG_URL,
archiveUrl: process.env.ARCHIVE_URL,
+ blogPublicUrl: process.env.BLOG_PUBLIC_URL,
+ archivePublicUrl: process.env.ARCHIVE_PUBLIC_URL,
+ tootToken: process.env.TOOT_TOKEN,
+ mastodonDomain: process.env.MASTODON_DOMAIN,
date: (new Date()).toISOString().split('T')[0],
- generateGemtext(posts) {
+ generateGemtext(title, text) {
- const title = posts.length === 1 ? 'A link' : `${posts.length} links`;
+ return `# ${title}\n\n${text}`;
+ },
- const linkText = posts.map((pin) => {
- return `=> ${pin.href} ${pin.description}\n${pin.extended}`;
+ getText(posts) {
+
+ return posts.map((post) => {
+
+ return `=> ${post.url} ${post.title}\n${post.notes}`;
}).join('\n\n');
+ },
+
+ getTitle(posts) {
+
+ if (posts.length === 1) {
+ return `Link: ${posts[0].title}`;
+ }
+ return `${posts.length} links for ${internals.date}`;
+ },
+
+ slugify(text) {
+
+ return text.toLowerCase().replace(/[^a-z0-9 ]/g, '').replace(/ +/g, '-')
+ },
+
+ async toot(title) {
+
+ const body = new FormData();
+ body.set(
+ 'status',
+ `New post: ${title}\n\nAvailable on:\n\nāļø the gemini archive ${internals.archivePublicUrl}\n\n or, the ephemeral blog š: ${internals.blogPublicUrl}`
+ );
+ return fetch(`https://${internals.mastodonDomain}/api/v1/statuses`, {
+ method: 'POST',
+ headers: {
+ Authorization: `Bearer ${internals.tootToken}`,
+ },
+ body
+ });
+ },
+
+ async getBookmarks() {
+
+ const url = join(internals.apiUrl, 'bookmarks') + '?q=%23linkblog';
+ const response = await fetch(url, {
+ headers: {
+ 'Content-Type': 'application/json',
+ Authorization: `Token ${internals.apiToken}`
+ }
+ });
+ const data = await response.json();
+
+ return data.results;
+ },
+
+ async updateBookmark(bookmark) {
+
+ console.log(bookmark.tag_names);
+ console.log(bookmark.tag_names.map((tag) => tag === 'linkblog' ? 'linkblog-posted' : tag));
+
+ const url = join(internals.apiUrl, 'bookmarks', `${bookmark.id}`)
+ const response = await fetch(url, {
+ method: 'PATCH',
+ body: JSON.stringify(
+ {
+ tag_names: bookmark.tag_names.map((tag) => tag === 'linkblog' ? 'linkblog-posted' : tag)
+ }
+ ),
+ headers: {
+ 'Content-Type': 'application/json',
+ Authorization: `Token ${internals.apiToken}`
+ }
+ });
- return `# ${title} for ${internals.date}\n\n${linkText}`;
+ const data = await response.text();
+ console.log(url);
+ console.log(data);
}
};
async function run() {
- const pinboard = new Pinboard(internals.apiToken);
- const getPins = promisify(pinboard.get);
- const addPin = promisify(pinboard.add);
+ const bookmarks = await internals.getBookmarks();
- const pins = await getPins({ tag: 'linkblog' });
-
- if (pins.posts.length === 0) {
+ if (bookmarks.length === 0) {
console.error('No links to post');
return;
}
- const gemtext = internals.generateGemtext(pins.posts);
- const gemfile = resolve(join(__dirname, `linkblog-${internals.date}.gmi`));
+ const title = internals.getTitle(bookmarks);
+ const text = internals.getText(bookmarks);
+ const gemtext = internals.generateGemtext(title, text);
+ const filename = internals.slugify(title);
+
+ const gemfile = resolve(join(__dirname, `${filename}.gmi`));
await writeFile(gemfile, gemtext);
- await internals.exec(`blog --add ${gemfile}`);
- await internals.exec(`blog --publish ${internals.blogUrl}`);
- await internals.exec(`blog --publish-archive ${internals.archiveUrl}`);
+ await internals.exec(`blog add ${gemfile}`);
+ await internals.exec(`blog publish ${internals.blogUrl}`);
+ await internals.exec(`blog publish-archive ${internals.archiveUrl}`);
await rm(gemfile);
- for (const pin of pins.posts) {
- await addPin({
- url: pin.href,
- description: pin.description,
- extended: pin.extended,
- dt: pin.time,
- tags: pin.tags.replace('linkblog', 'linkblog-posted')
- });
+ for (const bookmark of bookmarks) {
+ await internals.updateBookmark(bookmark);
+ }
+
+ if (internals.tootToken) {
+ await internals.toot(title);
}
}