Skip to content

Commit

Permalink
Support overriding status template
Browse files Browse the repository at this point in the history
  • Loading branch information
joschi committed Dec 28, 2022
1 parent 5a925c6 commit f90d7f7
Show file tree
Hide file tree
Showing 12 changed files with 292 additions and 44 deletions.
28 changes: 26 additions & 2 deletions .github/workflows/integration-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ jobs:
uses: './'
with:
# This is the RSS feed you want to publish
rss-feed: 'https://githubraw.com/joschi/mastofeedbot/main/tests/simple.xml'
rss-feed: 'https://githubraw.com/joschi/mastofeedbot/main/tests/simple-no-cache.xml'
# Visibility of the posted status (public | unlisted | private | direct)
status-visibility: private
dry-run: false
Expand Down Expand Up @@ -83,7 +83,7 @@ jobs:
uses: './'
with:
# This is the RSS feed you want to publish
rss-feed: 'https://githubraw.com/joschi/mastofeedbot/main/tests/simple.xml'
rss-feed: 'https://githubraw.com/joschi/mastofeedbot/main/tests/simple-sensitive.xml'
# Visibility of the posted status (public | unlisted | private | direct)
status-visibility: unlisted
# Mark Mastodon status as sensitive content
Expand All @@ -94,3 +94,27 @@ jobs:
api-token: ${{ secrets.MASTODON_ACCESS_TOKEN }}
# This is a path to the cache file, using the above cache path
cache-file: ${{ github.workspace }}/mastofeedbot/cache.json

simple-template:
runs-on: ubuntu-latest
steps:
- name: Checkout repo
uses: actions/checkout@755da8c3cf115ac066823e79a1e1788f8940201b # v3
- name: Run action
uses: './'
with:
# This is the RSS feed you want to publish
rss-feed: 'https://githubraw.com/joschi/mastofeedbot/main/tests/simple-template.xml'
# Visibility of the posted status (public | unlisted | private | direct)
status-visibility: unlisted
# Template of status posted to Mastodon (Handlebars)
template: |
{{feedData.title}}: {{item.title}}
{{item.link}}
# This is your instance address
api-endpoint: https://social.dev-wiki.de/
# This is the secret you created earlier
api-token: ${{ secrets.MASTODON_ACCESS_TOKEN }}
# This is a path to the cache file, using the above cache path
cache-file: ${{ github.workspace }}/mastofeedbot/cache.json
27 changes: 27 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ jobs:
with:
# This is the RSS feed you want to publish
rss-feed: https://www.githubstatus.com/history.rss
# Template of status posted to Mastodon (Handlebars)
template: '{{item.title}} {{item.link}}'
# Visibility of the posted status (public | unlisted | private | direct)
status-visibility: public
# Mark Mastodon status as sensitive content
Expand All @@ -56,3 +58,28 @@ jobs:
```
5. Commit and publish your changes.
## Status template
The status template (`status-template`) is using [Handlebars](https://handlebarsjs.com/) as template engine.

The action is passing in an instance of `FeedData` (field `feedData`) and the current `FeedEntry` (field `item`) into the template:

```typescript
export interface FeedEntry {
link?: string;
title?: string;
description?: string;
published?: Date;
}
export interface FeedData {
link?: string;
title?: string;
description?: string;
generator?: string;
language?: string;
published?: Date;
entries?: Array<FeedEntry>;
}
```
4 changes: 4 additions & 0 deletions action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@ inputs:
description: 'Visibility of the posted status (public | unlisted | private | direct)'
required: false
default: 'public'
template:
description: 'Template of status posted to Mastodon (Handlebars)'
required: true
default: '{{item.title}} {{item.link}}'
dry-run:
description: 'Only fetch RSS feed and update cache but skip posting to Mastodon.'
required: false
Expand Down
68 changes: 45 additions & 23 deletions dist/index.js

Large diffs are not rendered by default.

8 changes: 4 additions & 4 deletions dist/index.js.map

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions dist/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
"dependencies": {
"@actions/core": "^1.10.0",
"@extractus/feed-extractor": "^6.1.7",
"handlebars": "^4.7.7",
"masto": "^4.11.1",
"mkdirp": "^1.0.4"
}
Expand Down
53 changes: 51 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
"dependencies": {
"@actions/core": "^1.10.0",
"@extractus/feed-extractor": "^6.1.7",
"handlebars": "^4.7.7",
"masto": "^4.11.1",
"mkdirp": "^1.0.4"
}
Expand Down
38 changes: 25 additions & 13 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@ import { login, StatusVisibility, type MastoClient } from 'masto';
import { readFile, writeFile } from 'fs/promises';
import * as core from '@actions/core';
import mkdirp from 'mkdirp';
import { type FeedEntry, read } from '@extractus/feed-extractor';
import { type FeedEntry, FeedData, read } from '@extractus/feed-extractor';
import crypto from 'crypto';
import Handlebars from "handlebars";

function sha256(data: string): string {
return crypto.createHash('sha256').update(data, 'utf-8').digest('hex')
Expand All @@ -28,11 +29,18 @@ async function writeCache(cacheFile: string, cacheLimit: number, cache: string[]
}

async function postItems(
apiEndpoint: string, apiToken: string, rss: FeedEntry[],
visibility: StatusVisibility, dryRun: boolean, sensitive: boolean, cache: string[]) {
apiEndpoint: string,
apiToken: string,
feedData: FeedData | undefined,
entries: FeedEntry[],
statusTemplate: HandlebarsTemplateDelegate<any>,
visibility: StatusVisibility,
dryRun: boolean,
sensitive: boolean,
cache: string[]) {
if (dryRun) {
// Add new items to cache
for (const item of rss) {
for (const item of entries) {
try {
const hash = sha256(<string>item.link);
core.debug(`Adding ${item.title} with hash ${hash} to cache`);
Expand Down Expand Up @@ -60,14 +68,14 @@ async function postItems(
}

// post the new items
for (const item of rss) {
for (const item of entries) {
try {
const hash = sha256(<string>item.link);
core.debug(`Posting ${item.title} with hash ${hash}`);

// post the item
const res = await masto.statuses.create({
status: `${item.title} ${item.link}`,
status: statusTemplate({ feedData, item }),
visibility,
sensitive
}, hash);
Expand All @@ -92,11 +100,11 @@ async function filterCachedItems(rss: FeedEntry[], cache: string[]): Promise<Fee
return rss;
}

async function getRss(rssFeed: string): Promise<FeedEntry[] | void> {
let rss: FeedEntry[];
async function getRss(rssFeed: string): Promise<FeedData | undefined> {
let rss: FeedData;
try {
rss = <FeedEntry[]>(await read(rssFeed)).entries;
core.debug(JSON.stringify(`Pre-filter feed items:\n\n${JSON.stringify(rss, null, 2)}`));
rss = <FeedData>(await read(rssFeed));
core.debug(JSON.stringify(`Pre-filter feed items:\n\n${JSON.stringify(rss.entries, null, 2)}`));
return rss;
} catch (e) {
core.setFailed(`Failed to parse RSS feed: ${(<Error>e).message}`);
Expand Down Expand Up @@ -129,22 +137,26 @@ export async function main(): Promise<void> {
core.debug(`cacheLimit: ${cacheLimit}`);
const statusVisibility: StatusVisibility = <StatusVisibility>core.getInput('status-visibility', { trimWhitespace: true });
core.debug(`statusVisibility: ${statusVisibility}`);
const template: string = core.getInput('template');
core.debug(`template: ${template}`);
const dryRun: boolean = core.getBooleanInput('dry-run');
core.debug(`dryRun: ${dryRun}`);
const sensitive: boolean = core.getBooleanInput('sensitive');
core.debug(`sensitive: ${sensitive}`);

// get the rss feed
let rss = await getRss(rssFeed);
const feedData: FeedData | undefined = await getRss(rssFeed);
const entries: FeedEntry[] = feedData?.entries ?? [];

// get the cache
const cache = await getCache(cacheFile);

// filter out the cached items
rss = await filterCachedItems(<FeedEntry[]>rss, cache);
const filteredEntries: FeedEntry[] = await filterCachedItems(entries, cache);

// post the new items
await postItems(apiEndpoint, apiToken, <FeedEntry[]>rss, statusVisibility, dryRun, sensitive, cache);
const statusTemplate = Handlebars.compile(template);
await postItems(apiEndpoint, apiToken, feedData, entries, statusTemplate, statusVisibility, dryRun, sensitive, cache);

// write the cache
await writeCache(cacheFile, cacheLimit, cache);
Expand Down
36 changes: 36 additions & 0 deletions tests/simple-no-cache.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<rss version="2.0">
<channel>
<link>https://raw.githubusercontent.com/joschi/mastofeedbot/main/tests/simple.rss</link>
<title>Channel Title</title>
<description>Channel description.</description>
<managingEditor>joe.user@example.com (Managing Editor)</managingEditor>
<lastBuildDate>Tue, 27 Dec 2022 07:17:21 +0000</lastBuildDate>
<pubDate>Tue, 27 Dec 2022 07:17:21 +0000</pubDate>
<docs>http://blogs.law.harvard.edu/tech/rss</docs>
<image>
<url>https://avatars.githubusercontent.com/u/43951</url>
<link>https://raw.githubusercontent.com/joschi/mastofeedbot/main/tests/simple.rss</link>
<title>Image Title</title>
<description>Image description.</description>
</image>
<item>
<link>https://github.com/joschi/mastofeedbot/pull/1#no-cache</link>
<guid isPermaLink="false">44aefc891f5b1f96ae7393f3d1613254eae9c23b</guid>
<title>Item 1 Title</title>
<description>Item 1 Description</description>
<pubDate>Thu, 15 Dec 2022 19:02:13 +0000</pubDate>
<category>item1:category</category>
<author>author.item1@example.com (Author Item 1)</author>
</item>
<item>
<link>https://github.com/joschi/mastofeedbot/pull/2#no-cache</link>
<guid isPermaLink="false">55a26da9618a994e56c845306bd38641f58220af</guid>
<title>Item 2 Title</title>
<description>Item 2 Description</description>
<pubDate>Tue, 27 Dec 2022 19:02:13 +0000</pubDate>
<category>item2:category</category>
<author>author.item2@example.com (Author Item 2)</author>
</item>
</channel>
</rss>
36 changes: 36 additions & 0 deletions tests/simple-sensitive.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<rss version="2.0">
<channel>
<link>https://raw.githubusercontent.com/joschi/mastofeedbot/main/tests/simple.rss</link>
<title>Channel Title</title>
<description>Channel description.</description>
<managingEditor>joe.user@example.com (Managing Editor)</managingEditor>
<lastBuildDate>Tue, 27 Dec 2022 07:17:21 +0000</lastBuildDate>
<pubDate>Tue, 27 Dec 2022 07:17:21 +0000</pubDate>
<docs>http://blogs.law.harvard.edu/tech/rss</docs>
<image>
<url>https://avatars.githubusercontent.com/u/43951</url>
<link>https://raw.githubusercontent.com/joschi/mastofeedbot/main/tests/simple.rss</link>
<title>Image Title</title>
<description>Image description.</description>
</image>
<item>
<link>https://github.com/joschi/mastofeedbot/pull/1#sensitive</link>
<guid isPermaLink="false">44aefc891f5b1f96ae7393f3d1613254eae9c23b</guid>
<title>Item 1 Title</title>
<description>Item 1 Description</description>
<pubDate>Thu, 15 Dec 2022 19:02:13 +0000</pubDate>
<category>item1:category</category>
<author>author.item1@example.com (Author Item 1)</author>
</item>
<item>
<link>https://github.com/joschi/mastofeedbot/pull/2#sensitive</link>
<guid isPermaLink="false">55a26da9618a994e56c845306bd38641f58220af</guid>
<title>Item 2 Title</title>
<description>Item 2 Description</description>
<pubDate>Tue, 27 Dec 2022 19:02:13 +0000</pubDate>
<category>item2:category</category>
<author>author.item2@example.com (Author Item 2)</author>
</item>
</channel>
</rss>
Loading

0 comments on commit f90d7f7

Please sign in to comment.