---
# System prepended metadata

title: bluesky bot reposting arxiv RSS

---


# Design

- Implement a JavaScript code that reads https://arxiv.org/rss/stat by `rss-parser` and posts them to bluesky by `@atproto/api`.
- Put the above code on Google Cloud Functions with Pub/Sub trigger.
- Execute the above Cloud Function by Google Cloud Scheduler (once per day).

# Code

package.json
```json
{
  "dependencies": {
    "@google-cloud/functions-framework": "^3.0.0",
    "@atproto/api": "^0.4.0",
    "rss-parser": "^3.13.0"
  }
}

```

index.js
```javascript
const {BskyAgent, RichText, AppBskyFeedPost} = require("@atproto/api")
const Parser = require('rss-parser')

async function get_feeds(url) {
  const parser = new Parser()
  const feed = await parser.parseURL(url);
  let output = [];
  for (const item of feed.items) {
    if (!item.title.endsWith("UPDATED)")) {
      output.push({
        title: item.title,
        link: item.link
      });
    }
  }
  return output;
}
async function post(item) {
  const agent = new BskyAgent({ service: "https://bsky.social" });
  await agent.login({
    identifier: "arxiv-stat.bsky.social",
    password: "xxxx-xxxx-xxxx-xxxx", // app password
  });
  rt = new RichText({text: item.title + "\n" + item.link});
  await rt.detectFacets(agent)
  const post = {
    $type: 'app.bsky.feed.post',
    text: rt.text,
    facets: rt.facets,
    createdAt: new Date().toISOString()
  }
  const res = AppBskyFeedPost.validateRecord(post)
  if (res.success) {
    console.log(post)
    await agent.post(post);
  } else {
    console.log(res.error)
  }
}

const functions = require('@google-cloud/functions-framework');

functions.http('main', async (req, res) => {
  const url = "https://export.arxiv.org/rss/stat";
  const feeds = await get_feeds(url);
  let response = ""
  for (const feed of feeds) {
    response += `${feed.title + "\n" + feed.link + "\n"}`;
    await post(feed)
  }
  res.send(response);
});
```
