Skip to content

Commit 877aa70

Browse files
authored
Support overriding status template (#18)
Refs selfagency#8 Refs https://github.com/handlebars-lang/handlebars.js
1 parent 5a925c6 commit 877aa70

File tree

12 files changed

+292
-44
lines changed

12 files changed

+292
-44
lines changed

.github/workflows/integration-tests.yml

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ jobs:
4343
uses: './'
4444
with:
4545
# This is the RSS feed you want to publish
46-
rss-feed: 'https://githubraw.com/joschi/mastofeedbot/main/tests/simple.xml'
46+
rss-feed: 'https://githubraw.com/joschi/mastofeedbot/main/tests/simple-no-cache.xml'
4747
# Visibility of the posted status (public | unlisted | private | direct)
4848
status-visibility: private
4949
dry-run: false
@@ -83,7 +83,7 @@ jobs:
8383
uses: './'
8484
with:
8585
# This is the RSS feed you want to publish
86-
rss-feed: 'https://githubraw.com/joschi/mastofeedbot/main/tests/simple.xml'
86+
rss-feed: 'https://githubraw.com/joschi/mastofeedbot/main/tests/simple-sensitive.xml'
8787
# Visibility of the posted status (public | unlisted | private | direct)
8888
status-visibility: unlisted
8989
# Mark Mastodon status as sensitive content
@@ -94,3 +94,27 @@ jobs:
9494
api-token: ${{ secrets.MASTODON_ACCESS_TOKEN }}
9595
# This is a path to the cache file, using the above cache path
9696
cache-file: ${{ github.workspace }}/mastofeedbot/cache.json
97+
98+
simple-template:
99+
runs-on: ubuntu-latest
100+
steps:
101+
- name: Checkout repo
102+
uses: actions/checkout@755da8c3cf115ac066823e79a1e1788f8940201b # v3
103+
- name: Run action
104+
uses: './'
105+
with:
106+
# This is the RSS feed you want to publish
107+
rss-feed: 'https://githubraw.com/joschi/mastofeedbot/main/tests/simple-template.xml'
108+
# Visibility of the posted status (public | unlisted | private | direct)
109+
status-visibility: unlisted
110+
# Template of status posted to Mastodon (Handlebars)
111+
template: |
112+
{{feedData.title}}: {{item.title}}
113+
114+
{{item.link}}
115+
# This is your instance address
116+
api-endpoint: https://social.dev-wiki.de/
117+
# This is the secret you created earlier
118+
api-token: ${{ secrets.MASTODON_ACCESS_TOKEN }}
119+
# This is a path to the cache file, using the above cache path
120+
cache-file: ${{ github.workspace }}/mastofeedbot/cache.json

README.md

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,8 @@ jobs:
4343
with:
4444
# This is the RSS feed you want to publish
4545
rss-feed: https://www.githubstatus.com/history.rss
46+
# Template of status posted to Mastodon (Handlebars)
47+
template: '{{item.title}} {{item.link}}'
4648
# Visibility of the posted status (public | unlisted | private | direct)
4749
status-visibility: public
4850
# Mark Mastodon status as sensitive content
@@ -56,3 +58,28 @@ jobs:
5658
```
5759
5860
5. Commit and publish your changes.
61+
62+
## Status template
63+
64+
The status template (`status-template`) is using [Handlebars](https://handlebarsjs.com/) as template engine.
65+
66+
The action is passing in an instance of `FeedData` (field `feedData`) and the current `FeedEntry` (field `item`) into the template:
67+
68+
```typescript
69+
export interface FeedEntry {
70+
link?: string;
71+
title?: string;
72+
description?: string;
73+
published?: Date;
74+
}
75+
76+
export interface FeedData {
77+
link?: string;
78+
title?: string;
79+
description?: string;
80+
generator?: string;
81+
language?: string;
82+
published?: Date;
83+
entries?: Array<FeedEntry>;
84+
}
85+
```

action.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,10 @@ inputs:
1212
description: 'Visibility of the posted status (public | unlisted | private | direct)'
1313
required: false
1414
default: 'public'
15+
template:
16+
description: 'Template of status posted to Mastodon (Handlebars)'
17+
required: true
18+
default: '{{item.title}} {{item.link}}'
1519
dry-run:
1620
description: 'Only fetch RSS feed and update cache but skip posting to Mastodon.'
1721
required: false

dist/index.js

Lines changed: 45 additions & 23 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/index.js.map

Lines changed: 4 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@
4242
"dependencies": {
4343
"@actions/core": "^1.10.0",
4444
"@extractus/feed-extractor": "^6.1.7",
45+
"handlebars": "^4.7.7",
4546
"masto": "^4.11.1",
4647
"mkdirp": "^1.0.4"
4748
}

package-lock.json

Lines changed: 51 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@
4242
"dependencies": {
4343
"@actions/core": "^1.10.0",
4444
"@extractus/feed-extractor": "^6.1.7",
45+
"handlebars": "^4.7.7",
4546
"masto": "^4.11.1",
4647
"mkdirp": "^1.0.4"
4748
}

src/index.ts

Lines changed: 25 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,9 @@ import { login, StatusVisibility, type MastoClient } from 'masto';
22
import { readFile, writeFile } from 'fs/promises';
33
import * as core from '@actions/core';
44
import mkdirp from 'mkdirp';
5-
import { type FeedEntry, read } from '@extractus/feed-extractor';
5+
import { type FeedEntry, FeedData, read } from '@extractus/feed-extractor';
66
import crypto from 'crypto';
7+
import Handlebars from "handlebars";
78

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

3031
async function postItems(
31-
apiEndpoint: string, apiToken: string, rss: FeedEntry[],
32-
visibility: StatusVisibility, dryRun: boolean, sensitive: boolean, cache: string[]) {
32+
apiEndpoint: string,
33+
apiToken: string,
34+
feedData: FeedData | undefined,
35+
entries: FeedEntry[],
36+
statusTemplate: HandlebarsTemplateDelegate<any>,
37+
visibility: StatusVisibility,
38+
dryRun: boolean,
39+
sensitive: boolean,
40+
cache: string[]) {
3341
if (dryRun) {
3442
// Add new items to cache
35-
for (const item of rss) {
43+
for (const item of entries) {
3644
try {
3745
const hash = sha256(<string>item.link);
3846
core.debug(`Adding ${item.title} with hash ${hash} to cache`);
@@ -60,14 +68,14 @@ async function postItems(
6068
}
6169

6270
// post the new items
63-
for (const item of rss) {
71+
for (const item of entries) {
6472
try {
6573
const hash = sha256(<string>item.link);
6674
core.debug(`Posting ${item.title} with hash ${hash}`);
6775

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

95-
async function getRss(rssFeed: string): Promise<FeedEntry[] | void> {
96-
let rss: FeedEntry[];
103+
async function getRss(rssFeed: string): Promise<FeedData | undefined> {
104+
let rss: FeedData;
97105
try {
98-
rss = <FeedEntry[]>(await read(rssFeed)).entries;
99-
core.debug(JSON.stringify(`Pre-filter feed items:\n\n${JSON.stringify(rss, null, 2)}`));
106+
rss = <FeedData>(await read(rssFeed));
107+
core.debug(JSON.stringify(`Pre-filter feed items:\n\n${JSON.stringify(rss.entries, null, 2)}`));
100108
return rss;
101109
} catch (e) {
102110
core.setFailed(`Failed to parse RSS feed: ${(<Error>e).message}`);
@@ -129,22 +137,26 @@ export async function main(): Promise<void> {
129137
core.debug(`cacheLimit: ${cacheLimit}`);
130138
const statusVisibility: StatusVisibility = <StatusVisibility>core.getInput('status-visibility', { trimWhitespace: true });
131139
core.debug(`statusVisibility: ${statusVisibility}`);
140+
const template: string = core.getInput('template');
141+
core.debug(`template: ${template}`);
132142
const dryRun: boolean = core.getBooleanInput('dry-run');
133143
core.debug(`dryRun: ${dryRun}`);
134144
const sensitive: boolean = core.getBooleanInput('sensitive');
135145
core.debug(`sensitive: ${sensitive}`);
136146

137147
// get the rss feed
138-
let rss = await getRss(rssFeed);
148+
const feedData: FeedData | undefined = await getRss(rssFeed);
149+
const entries: FeedEntry[] = feedData?.entries ?? [];
139150

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

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

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

149161
// write the cache
150162
await writeCache(cacheFile, cacheLimit, cache);

tests/simple-no-cache.xml

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
2+
<rss version="2.0">
3+
<channel>
4+
<link>https://raw.githubusercontent.com/joschi/mastofeedbot/main/tests/simple.rss</link>
5+
<title>Channel Title</title>
6+
<description>Channel description.</description>
7+
<managingEditor>joe.user@example.com (Managing Editor)</managingEditor>
8+
<lastBuildDate>Tue, 27 Dec 2022 07:17:21 +0000</lastBuildDate>
9+
<pubDate>Tue, 27 Dec 2022 07:17:21 +0000</pubDate>
10+
<docs>http://blogs.law.harvard.edu/tech/rss</docs>
11+
<image>
12+
<url>https://avatars.githubusercontent.com/u/43951</url>
13+
<link>https://raw.githubusercontent.com/joschi/mastofeedbot/main/tests/simple.rss</link>
14+
<title>Image Title</title>
15+
<description>Image description.</description>
16+
</image>
17+
<item>
18+
<link>https://github.com/joschi/mastofeedbot/pull/1#no-cache</link>
19+
<guid isPermaLink="false">44aefc891f5b1f96ae7393f3d1613254eae9c23b</guid>
20+
<title>Item 1 Title</title>
21+
<description>Item 1 Description</description>
22+
<pubDate>Thu, 15 Dec 2022 19:02:13 +0000</pubDate>
23+
<category>item1:category</category>
24+
<author>author.item1@example.com (Author Item 1)</author>
25+
</item>
26+
<item>
27+
<link>https://github.com/joschi/mastofeedbot/pull/2#no-cache</link>
28+
<guid isPermaLink="false">55a26da9618a994e56c845306bd38641f58220af</guid>
29+
<title>Item 2 Title</title>
30+
<description>Item 2 Description</description>
31+
<pubDate>Tue, 27 Dec 2022 19:02:13 +0000</pubDate>
32+
<category>item2:category</category>
33+
<author>author.item2@example.com (Author Item 2)</author>
34+
</item>
35+
</channel>
36+
</rss>

tests/simple-sensitive.xml

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
2+
<rss version="2.0">
3+
<channel>
4+
<link>https://raw.githubusercontent.com/joschi/mastofeedbot/main/tests/simple.rss</link>
5+
<title>Channel Title</title>
6+
<description>Channel description.</description>
7+
<managingEditor>joe.user@example.com (Managing Editor)</managingEditor>
8+
<lastBuildDate>Tue, 27 Dec 2022 07:17:21 +0000</lastBuildDate>
9+
<pubDate>Tue, 27 Dec 2022 07:17:21 +0000</pubDate>
10+
<docs>http://blogs.law.harvard.edu/tech/rss</docs>
11+
<image>
12+
<url>https://avatars.githubusercontent.com/u/43951</url>
13+
<link>https://raw.githubusercontent.com/joschi/mastofeedbot/main/tests/simple.rss</link>
14+
<title>Image Title</title>
15+
<description>Image description.</description>
16+
</image>
17+
<item>
18+
<link>https://github.com/joschi/mastofeedbot/pull/1#sensitive</link>
19+
<guid isPermaLink="false">44aefc891f5b1f96ae7393f3d1613254eae9c23b</guid>
20+
<title>Item 1 Title</title>
21+
<description>Item 1 Description</description>
22+
<pubDate>Thu, 15 Dec 2022 19:02:13 +0000</pubDate>
23+
<category>item1:category</category>
24+
<author>author.item1@example.com (Author Item 1)</author>
25+
</item>
26+
<item>
27+
<link>https://github.com/joschi/mastofeedbot/pull/2#sensitive</link>
28+
<guid isPermaLink="false">55a26da9618a994e56c845306bd38641f58220af</guid>
29+
<title>Item 2 Title</title>
30+
<description>Item 2 Description</description>
31+
<pubDate>Tue, 27 Dec 2022 19:02:13 +0000</pubDate>
32+
<category>item2:category</category>
33+
<author>author.item2@example.com (Author Item 2)</author>
34+
</item>
35+
</channel>
36+
</rss>

0 commit comments

Comments
 (0)