Add 'rss' bot: broadcasts an RSS/Atom feed to a channel
New rss bot type: on start it creates a broadcast channel (observer group with recent history on) and polls a configured feed URL; new posts are broadcast to the channel. Subscribers join the channel link (seen on the bot's profile); direct contacts get a welcome + the latest items and can send /new for the latest. Stdlib-only feed parsing (urllib + ElementTree), seeds existing items on startup so it doesn't replay the whole feed. Config: feed_url, poll_seconds. Adds rss_test.py (mock feed) — passes. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -49,6 +49,7 @@
|
||||
<table>
|
||||
<tr><td><span class="tag">echo</span></td><td class="muted">Repeats every message back to the sender — handy for testing a connection end to end.</td></tr>
|
||||
<tr><td><span class="tag">llm</span></td><td class="muted">Chat with a local or remote LLM (OpenAI-compatible, e.g. Ollama). Give it context, it replies to your messages.</td></tr>
|
||||
<tr><td><span class="tag">rss</span></td><td class="muted">Watches an RSS/Atom feed and broadcasts new posts to a channel it creates. Subscribers join the channel; send /new for the latest.</td></tr>
|
||||
<tr><td><span class="tag">broadcast</span></td><td class="muted">Relays messages from authorized publishers out to all of the bot's contacts.</td></tr>
|
||||
<tr><td><span class="tag">support</span></td><td class="muted">Business inbox — auto-replies with a welcome message and collects incoming inquiries.</td></tr>
|
||||
<tr><td><span class="tag">directory</span></td><td class="muted">Directory service for discovering and listing groups or contacts.</td></tr>
|
||||
@@ -224,6 +225,23 @@
|
||||
<input type="text" name="prohibited_message" placeholder="Only publishers can broadcast. Your message is deleted.">
|
||||
</div>
|
||||
</div>
|
||||
<div id="rss-fields" style="display:none;">
|
||||
<div style="border-top:1px solid var(--border);margin:4px 0 14px;padding-top:14px;">
|
||||
<p class="muted" style="margin-bottom:12px;">
|
||||
The bot watches this feed and broadcasts new posts to a channel it creates.
|
||||
Share the channel link (from the bot's profile) with subscribers; anyone messaging
|
||||
the bot can send <code>/new</code> for the latest.
|
||||
</p>
|
||||
</div>
|
||||
<div class="field">
|
||||
<label>Feed URL</label>
|
||||
<input type="text" name="feed_url" placeholder="https://example.com/feed.xml">
|
||||
</div>
|
||||
<div class="field">
|
||||
<label>Poll interval <span class="muted" style="font-weight:400;">(seconds)</span></label>
|
||||
<input type="number" name="poll_seconds" min="30" value="300">
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
<div class="flex gap-8 mt-16" style="justify-content:flex-end;">
|
||||
<button type="button" class="btn btn-ghost"
|
||||
@@ -297,6 +315,7 @@ function onTypeChange() {
|
||||
document.getElementById('deadmans-fields').style.display = (val === 'deadmans') ? 'block' : 'none';
|
||||
document.getElementById('directory-fields').style.display = (val === 'directory') ? 'block' : 'none';
|
||||
document.getElementById('broadcast-fields').style.display = (val === 'broadcast') ? 'block' : 'none';
|
||||
document.getElementById('rss-fields').style.display = (val === 'rss') ? 'block' : 'none';
|
||||
}
|
||||
{% endif %}
|
||||
|
||||
@@ -341,6 +360,13 @@ document.getElementById('create-form').addEventListener('submit', async (e) => {
|
||||
const prohibited = (fd.get('prohibited_message') || '').trim();
|
||||
if (prohibited) config.prohibited_message = prohibited;
|
||||
}
|
||||
if (botType === 'rss') {
|
||||
const url = (fd.get('feed_url') || '').trim();
|
||||
if (!url) { alert('Feed URL is required for an RSS bot'); return; }
|
||||
config.feed_url = url;
|
||||
const ps = parseInt(fd.get('poll_seconds'), 10);
|
||||
if (!isNaN(ps) && ps >= 30) config.poll_seconds = ps;
|
||||
}
|
||||
{% endif %}
|
||||
// Shared profile fields (users and bots)
|
||||
const bio = (fd.get('bio') || '').trim();
|
||||
|
||||
Reference in New Issue
Block a user