archive/poster.js (114 lines of code) (raw):

const { BskyAgent, AppBskyFeedPost } = require("@atproto/api"); // ### envrionment variables const dotenv = require('dotenv'); dotenv.config() console.log(process.env) // import dotenv from 'dotenv' // dotenv.config() const cheerio = require("cheerio"); const sharp = require("sharp"); const Parser = require("rss-parser"); const parser = new Parser(); const settings = [ { account: process.env.ACC, password: process.env.PASS, // url: "https://feeds.bbci.co.uk/news/uk/rss.xml#", // url: 'https://www.theguardian.com/au/rss' url: 'https://www.theguardian.com/data/rss' } ]; async function get_feeds(url) { const feed = await parser.parseURL(url); let output = []; for (const item of feed.items) { output.push({ title: item.title, link: item.link, }); } return output; } async function post(agent, item) { let post = { $type: "app.bsky.feed.post", text: item.title, createdAt: new Date().toISOString(), }; const dom = await fetch(item.link) .then((response) => response.text()) .then((html) => cheerio.load(html)); let description = null; const description_ = dom('head > meta[property="og:description"]'); if (description_) { description = description_.attr("content"); } let image_url = null; const image_url_ = dom('head > meta[property="og:image"]'); if (image_url_) { image_url = image_url_.attr("content"); } const buffer = await fetch(image_url) .then((response) => response.arrayBuffer()) .then((buffer) => sharp(buffer)) .then((s) => s.resize( s .resize(800, null, { fit: "inside", withoutEnlargement: true, }) .jpeg({ quality: 80, progressive: true, }) .toBuffer() ) ); post["embed"] = { external: { uri: item.link, title: item.title, description: description, }, $type: "app.bsky.embed.external", }; const res = AppBskyFeedPost.validateRecord(post); if (res.success) { console.log(post); agent.post(post); } else { console.log(res.error); } } async function main(setting) { const agent = new BskyAgent({ service: "https://bsky.social" }); await agent.login({ identifier: setting.account, password: setting.password, }); let processed = new Set(); let cursor = ""; let counter = 0 for (let i = 0; i < 3; ++i) { const response = await agent.getAuthorFeed({ actor: setting.account, limit: 100, cursor: cursor, }); cursor = response.cursor; for (const feed of response.data.feed) { processed.add(feed.post.record.embed.external.uri); processed.add(feed.post.record.text); } } for (const feed of await get_feeds(setting.url)) { if (counter < 5){ if (!processed.has(feed.title) && !processed.has(feed.link)) { await post(agent, feed); } else { console.log("skipped " + feed.title); } counter += 1 } } } for (const setting of settings) { console.log("process " + setting.url); main(setting); }